6

考虑:

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++ 会被破坏吗?

这甚至会有用吗?

4

6 回答 6

23

您是否需要此功能,或者这只是一个思想实验?

如果你需要这样做,常见的习惯用法是有一个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;
}
于 2009-06-20T13:35:14.443 回答
4

您真正要寻找的是虚拟副本构造函数,而 eduffy 发布的是标准的执行方式。

使用模板也有一些巧妙的方法。(免责声明:自我推销)

于 2009-06-20T13:37:31.117 回答
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 *
  ...

};

它仍然被认为是对 virtual 的有效覆盖,A::Clone();如果直接通过调用会更好B *

于 2010-05-29T18:43:51.517 回答
1

表达方式

new A(*b1)

已经有了意义,假设你有适当的重载。

如果它被赋予了不同的含义,则您必须提供另一种方式来获得其他含义。鉴于已经有一种方法可以获得您想要的含义,这有点毫无意义:

new B(*b1)

并猜测哪个更清晰易读。

于 2009-06-20T13:36:48.653 回答
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;
}
于 2009-06-20T19:58:34.377 回答
0

是的。不。

在不改变现有程序的含义或无法创建派生类在编译单元中已知时的基类。

构造函数和析构函数足够复杂,对于初学者来说可以理解。向它们注入更多的复杂性是不明智的。

于 2009-06-20T13:36:31.697 回答