对基本拷贝构造函数的显式调用=> RTTI信息丢失。错误?

时间:2014-01-12 14:35:21

标签: c++ copy-constructor rtti dynamic-cast

首先:

我只是出于好奇而问这个问题,以了解真正正在发生什么。我没有在这样的生产代码中使用,所以我希望看到建议另一种解决方案的答案。

拥有此代码:

class Base{
public:
    virtual void copy(){}
};

class Derived: public Base{
public:
    void copy(){
        Base a1;
        this->Base::Base(a1);//explicit call to base copy constructor
    }
};

我知道在某些情况下,显式调用复制构造函数是不好的。(当类动态分配成员时,因为对该内存区域的引用将丢失并且不再被释放)。

对于下面的例子,我没有看到调用基本拷贝构造函数的任何直接问题。乍一看,我认为在调用copy()方法时必须重新初始化基础子对象。

int main(){
    Base** _a = new Base*;
    _a[0] = new Derived(10);
    Derived* b = dynamic_cast<Derived*>(_a[0]);
    assert(b);//<===true
    _a[0]->copy();
    //t is still available and can be accessed through b
    std::cout<<b->t;//correct: 10
    b = (Derived*)_a[0];
    std::cout<<b->t;//correct: 10
    b = dynamic_cast<Derived*>(_a[0]);
    assert(b);//<===false       
}

然而第二个断言失败了。有人可以解释这种行为吗?为什么会这样?调用基本拷贝构造函数时,typeid是否丢失了?

我使用Visual Studio 2012编译了代码。

2 个答案:

答案 0 :(得分:3)

类成员初始化之前的构造函数将vptr指针设置为该类的虚函数表。手动调用父类的构造函数,使派生类vptr指向父类的vtable。

答案 1 :(得分:1)

好吧,当你调用Base::Base(const Base&)时,你正在为类型为Base的对象分配的内存中创建一个Derived类型的新对象。之后,所有虚拟功能都将指向他们的Base::实现。

如果要重新初始化对象,则必须调用派生类型Derived::Derived(const Derived&)的构造函数,不能只重新初始化它的一部分。

除了:
您可以通过首先破坏对象来使重新初始化更正:

this->~Derived();    //cleanly destruct the object
this->Derived::Derived(...);    //rebuilt the object in place