考虑:
class A
{
public:
A( int val ) : m_ValA( val ) {}
A( const A& rhs ) {}
int m_ValA;
};
class B : public A
{
public:
B( int val4A, int val4B ) : A( val4A ), m_ValB( val4B ) {}
B( const B& rhs ) : A( rhs ), m_ValB( rhs.m_ValB ) {}
int m_ValB;
};
int main()
{
A* b1 = new B( 1, 2 );
A* b2 = new A( *b1 ); // ERROR...but what if it could work?
return 0;
}
如果“new A( b1)”能够解析为创建新的B副本并返回A ,C ++会被破坏吗?
这会有用吗?
答案 0 :(得分:20)
您是否需要此功能,或者这只是一个思想实验?
如果你需要这样做,常见的习惯用法是Clone
方法:
class A
{
public:
A( int val ) : m_ValA( val ) {}
A( const A& rhs ) {}
virtual A *Clone () = 0;
int m_ValA;
};
class B : public A
{
public:
B( int val4A, int val4B ) : A( val4A ), m_ValB( val4B ) {}
B( const B& rhs ) : A( rhs ), m_ValB( rhs.m_ValB ) {}
A *Clone() { return new B(*this); }
int m_ValB;
};
int main()
{
A* b1 = new B( 1, 2 );
A* b2 = b1->Clone();
return 0;
}
答案 1 :(得分:4)
你真正想要的是virtual copy constructor,而eduffy发布的是标准的做法。
还有clever ways of doing it with templates。 (免责声明:自我推销)
答案 2 :(得分:2)
eduffy对答案的一小部分补充: 而不是
class B : public A {
...
A *Clone() { return new B(*this); }
...
};
你可以这样声明:
class B : public A {
...
B *Clone() { return new B(*this); } // note: returning B *
...
};
它仍被视为虚拟A::Clone();
的有效覆盖,如果直接通过B *
答案 3 :(得分:1)
表达式
new A(*b1)
已经有了意义,假设你有适当的超载。
如果给出了不同的含义,你必须提供另一种方法来获得另一种含义。鉴于已经有办法获得你想要的意思,这有点毫无意义:
new B(*b1)
猜猜哪个更清楚。
答案 4 :(得分:0)
是。没有。
有许多方法可以实现克隆(例如,或多或少的标准clone()方法,对象工厂的参数化变体,有或没有可配置的依赖注入),而不改变现有程序的含义,或者使其无法实现在编译单元中已知派生类时创建基类的实例。
构造函数和析构函数对于初学者来说足够复杂。向它们注入更多复杂性是不明智的。
答案 5 :(得分:0)
如上所述,有许多方法可以实现这一点。
如果new A( *b1 )
返回了B的新实例,则回答您的问题,那么这将不起作用。
int main()
{
A* b1 = new B( 1, 2 );
A a( *b1 ); // What size would 'a' be if it was polymorphicly constructed?
return 0;
}