【问题标题】:Copy constructor and composition复制构造函数和组合
【发布时间】:2012-01-07 17:05:45
【问题描述】:

我有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 的深拷贝,我就可以解决问题。这叫深拷贝吗?

附: A 和 B 是抽象类

【问题讨论】:

  • 你可以写那个函数,但它不是复制构造函数。
  • @BenjaminLindley:这应该是一个答案......
  • @OliCharlesworth:虽然我没有更好的解决方案(因为我不确定他要解决什么问题),但我认为这就是问题的核心。
  • 是的,你想解决 Ale 什么问题?
  • @Ale:是的,这可以称为深度复制。问题是A是一个抽象类,但是你需要复制一个实例的具体子类,但是由于你不知道调用哪个复制构造函数,你需要一个抽象的Clone()函数。稍后我会发布一个详细的答案。

标签: c++ copy-constructor


【解决方案1】:

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

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

你为什么需要它?您可以通过执行以下操作访问复制构造函数中的 mA 成员(我可能犯了一些语法错误):

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

【讨论】:

  • 为了迂腐,复制构造函数还有几个其他有效签名(例如B(B &))。
  • 这不是复制构造函数的定义,因此“按定义”是不准确的。例如。 B(const B &mB, A *pA = 0) 将是一个复制构造函数。
  • @OliCharlesworth:还有很多其他的有效签名,可能性几乎是无限的。
  • 为了完整起见,您可能需要提及三的规则,并建议提供B的赋值运算符。
  • @Ale:如果你想分配另一个对象,那么你不是在复制。所以听起来复制构造函数不是你应该看的。
【解决方案2】:

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

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;
}

【讨论】:

  • 啊,是的!好点子!显然我在考虑赋值运算符。 (虽然B b(b) 可能会编译...)
  • @OliCharlesworth:我将B b(b); 声明为“因为 PEBKC 的 UB”而不打扰。
  • @OliCharlesworth:为了好玩,我还添加了 ass.operator。这是绝对必要的自我分配证明:-)
  • 我更喜欢B& operator=(B const & rhs) { B tmp( rhs ); std::swap( mA, tmp.mA ); }。复制和交换样式非常适合这种情况。
  • @CharlesBailey:有趣的选择。它在这种情况下有效,但一般来说,它需要您为您的班级构建一个适当的swap 函数,不是吗?然后我会一路说B & operator=(B rhs) { swap(std::move(rhs)); }把副本的负担放在调用者身上:-)
猜你喜欢
  • 2013-10-13
  • 1970-01-01
  • 1970-01-01
  • 2020-05-14
  • 2016-09-12
  • 2013-04-04
  • 1970-01-01
  • 1970-01-01
  • 2014-11-21
相关资源
最近更新 更多