首先:
我只是出于好奇而问这个问题,以了解真正正在发生什么。我没有在这样的生产代码中使用,所以我不希望看到建议另一种解决方案的答案。
拥有此代码:
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编译了代码。
答案 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