我需要一个不同类实例的数组(这里是:B),它们共享相同的基类(这里:A)。
实例应存储为指针,因为它们在别处引用(此处不显示)
我这样试过:
class A {
public:
A() {}
};
class B : public A {
int m_magicValue;
public:
B() : A() , m_magicValue(4711){}
int getMagicValue() { return m_magicValue; }
};
class Manager {
std::vector<A*> m_array;
public:
Manager() {}
virtual ~Manager() {
for( size_t i=0; i<m_array.size(); i++ )
delete m_array[i];
m_array.clear();
}
void addA( const A& a ) {
// here A is copied - here the problem occurs
m_array.push_back( new A(a) );
// createSomeReferences( m_array.back() );
}
A& getA( size_t idx ) {
return *m_array[idx];
}
};
int main() {
B b;
Manager manager;
manager.addA(b);
B& copiedB = (B&) manager.getA(0);
int magic = copiedB.getMagicValue(); // magic is some random stuff instead of 4711!
return 0;
}
经理对B级一无所知,只知道A.
有趣的事情发生在addA()中:这里尝试新复制B并在数组中存储指针
但正如预期的那样它不能按预期工作;-)
copiedB.getMagicValue();返回一个随机值。
原因相对清楚:使用A的复制构造函数而不是B的复制构造函数,因此只复制A部分。
所以现在我的问题: 有没有一种很好的方法来实现这样一个继承整个类层次结构的副本,即使只知道基类?
答案 0 :(得分:5)
您需要一个虚拟的“克隆”功能(有时通俗地称为“虚拟副本构造函数”):
struct A
{
virtual ~A() { }
virtual A * clone() const = 0;
};
struct B : A
{
virtual A * clone() const
{
return new B(*this);
}
};
用法:
void addA(A const & a)
{
insert(a.clone());
}
使用原始指针是非常愚蠢的,并且最好在std::unique_ptr<A>
上键入克隆函数以及容器(并且代码几乎相同)。
(你现在可能会问自己,“为什么unique_ptr
版本已经进行了深度虚拟克隆,可能称为value_ptr<A>
?这是一个很好的问题。”