繁体   English   中英

如何复制包含指向其他几个成员之一的指针的对象?

[英]How to copy object which contains a pointer to one of several other members?

考虑一下:

class Base {};    
class A : public Base {};
class B : public Base {};
class C : public Base {};
class D : public Base {};

class Obj
{
public:
    Obj(const Obj&);

private:
    A _a;
    B _b;
    C _c;
    D _d;
    Base *_current;
};

_current始终指向_a_b_c_d ABCD可以具有不同的大小。 我想实现Obj(const Obj&)以便副本的_current指向自身本身的适当成员。

这种方法安全吗?

Obj::Obj(const Obj& obj) :
    _a {obj._a},
    _b {obj._b},
    _c {obj._c},
    _d {obj._d}
{
    auto objAAddr = reinterpret_cast<const char *>(&obj._a);
    auto objCurAddr = reinterpret_cast<const char *>(obj._current);
    auto diff = objCurAddr - objAAddr;
    auto myAAddr = reinterpret_cast<char *>(&_a);
    _current = reinterpret_cast<Base *>(myAAddr + diff);
}

“基地”地址可能是一些比其他_a “在这儿,就像&_obj (然后应用差异this )。

有更好/更清洁的选择吗?

要计算_current您应该添加到this之间的区别obj._current&obj 为了正确计算偏移量,您应该使用特殊类型uintptr_t char *不适合,因为在某些特定平台上char超过一个字节。

#include <cstdint>
Obj::Obj(const Obj& obj) :
    _a {obj._a},
    _b {obj._b},
    _c {obj._c},
    _d {obj._d}
{
    _current = reinterpret_cast<Base *>(reinterpret_cast<uintptr_t>(this) +
        (reinterpret_cast<const uintptr_t>(obj._current) - 
            reinterpret_cast<const uintptr_t>(&obj)));
}

我将在此处使用C样式转换:

Obj::Obj(const Obj& obj) :
    _a {obj._a},
    _b {obj._b},
    _c {obj._c},
    _d {obj._d}
{
    _current = (Base *)((uintptr_t)this +
        ((const uintptr_t)obj._current - (const uintptr_t)&obj));
}

临时多态性无需使用脆弱的指针算法即可实现。

class Base {};    
class A : public Base {};
class B : public Base {};
class C : public Base {};
class D : public Base {};

class Obj
{
public:
    Obj(const Obj&);
    Obj() { set_current(aa);  }
private:
    A _a;
    B _b;
    C _c;
    D _d;
    Base *_current;
    enum base_tag {
        aa, bb, cc, dd
    } tag;
    void set_current(base_tag t) {
        tag = t;
        switch (tag) {
        case aa: _current = &_a; break;
        case bb: _current = &_b; break;
        case cc: _current = &_c; break;
        case dd: _current = &_d; break;
        default: throw("gulp");
        }
    }
};

Obj::Obj(const Obj& obj) :
    _a {obj._a},
    _b {obj._b},
    _c {obj._c},
    _d {obj._d}
{
    set_current(obj.tag);
}

int main() {
    Obj o1;
    Obj o2{ o1 };
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM