复制构造函数和组合

Copy constructor and composition

本文关键字:组合 构造函数 复制      更新时间:2023-10-16

我有a类和B类之间的成分关系,

class A
{
    A(); //default constructor  //EDIT
    A(const A &mA); // copy constructor //EDIT
    virtual ~A();
};

class B
{
B(A *pA); //constructor
B(const B &mB) //copy constructor
virtual ~B(); //EDIT: destructor to eliminate mA and to build the composition
A* mA;
};

我可以这样写复制构造函数吗:

B(const B &mB, A *pA)

我需要它来保持复制对象之间的构图。它错了吗?是否存在更好的解决方案?谢谢

编辑:我会尽量解释得更好。我想要对象mB和对象mA的副本。但如果在副本构造函数中我写了mA=mB.mA,我会将地址复制到原始对象mA。所以我认为我需要一个深度副本,而不是一个吞咽副本。我的困惑出现了,因为现在,从主,首先我复制对象mA,然后我复制mB。这样做,我想我需要给复制的对象mA分配一个外部功能,比如

foo(A *pA)

否则,如果我能深入复制mB,我就能解决这个问题。这叫深度复制吗?

p.S。A和B是抽象类

否。根据定义,复制构造函数不能像您描述的那样具有签名。以下是复制构造函数的一些有效签名:

B(const B &);
B(B &);   // Thanks Oli!

你为什么需要它?你可以通过这样做来访问复制构造函数中的mA成员(我可能犯了一些语法错误):

B::B(const B & original)
{
    mA = original.mA;
}

您可能想得太多了。复制构造函数只需要将所有成员初始化为源对象的相应值,例如:

B(B const & rhs) : mA(rhs.mA) { }

不过,这只是一个微不足道的副本,所以如果没有其他内容,那么你最好根本不写任何副本构造函数。

另一方面,如果你想要一个深度副本,它可能是这样的:

B(B const & rhs) : mA(::new A(rhs.mA)) { }

然而,其细节取决于类B相对于指针对象mA的实际所有权策略。根据这些细节,如果需要,不要忘记编写一个合适的析构函数。

您还应该为您的复制构造函数编写一个匹配的赋值运算符来做一些不平凡的事情,例如:

B & operator=(B const & rhs)
{
    if (this != &rhs)
    {
        A * tmp = ::new A(*rhs.mA);    // need try/catch in general!
        ::delete mA; // OK, no exception occurred if we got here
        mA = tmp;
    }
    return *this;
}