C ++我应该在派生类中覆盖复制构造函数

时间:2013-12-13 16:56:33

标签: c++ class inheritance c++11

我有自定义复制构造函数的基类,它负责处理已分配的内存。 我也从那个基地开过课。派生类没有对内存做更多的事情。

如何复制构造函数在dervied类中查找? 如何覆盖交换,移动和分配?

3 个答案:

答案 0 :(得分:3)

除了swap之外,您不应该做任何其他事情。在这方面,基类就像数据成员,编译器生成的复制构造函数和赋值(如果适用则移动)包括它。

swap是不同的,因为没有编译器生成的swap,只是命名空间std中的默认实现,然后是程序员为用户定义的类型定义的任何特化或ADL重载

所以如果已经有一个看起来像这样的函数:

namespace foo {
    void swap(Base &lhs, Base &rhs) {
        lhs.swap(rhs); // or maybe the gory details are in this function
    }
}

你什么都不做,有些用户称之为:

foo::swap(derived1, derived2);

然后基础部分将被交换,派生的部分将不会,这是非常糟糕的。

用户不应该像那样调用交换,但你知道用户是什么样的。如果BaseDerived位于同一名称空间中,对用户来说可能看起来特别诱人,他们只是假设它一切正常。因此,如果您认为您的用户(或您自己的代码库)在调用Derived的方式中没有原则,那么您可能希望确保swap超载以阻止它们。

用户应拨打swap,如:

using std::swap;
swap(base1, base2);
swap(derived1, derived2);

foo::swapBase一起使用时,std::swap会调用Derivedstd::swap<Derived>可能效率低下(如果Base为实现效率而实施了交换,那么Derived也应该这样做。因此,您可能也希望为swap实现Derived,但速度慢并不像错误那么糟糕。

那就是说,你问的是移动。如果Derived可以有效移动,那么std::swap<Derived>也不错。也许它可以改进,也许不是,但它应该是边缘的,因为三个动作很难被击败。

您和用户也应该意识到swap不能很好地处理多态(因为通常两个对象必须具有相同的完整类型才能交换它们才有意义),并为基础实现它上课可能会带来麻烦。

Derived d1, d2;
Base &b1 = &d1, &b2 = d2;
swap(b1, d2); // swaps just the base part
swap(b1, b2); // swaps just the base part

首先,用户需要知道不要像那样调用swap。其次,您可能需要考虑具有Base的{​​{1}}是否真的设计为基类。

答案 1 :(得分:1)

有所谓的五阶规则(以前称为三阶规则),它表示如果你有用户定义的任何规则:

  • 复制构造函数
  • 移动构造函数
  • copy assignment-operator
  • move assignment-operator

比您可能还想要用户定义其他四个。


另一方面,有rule-of-zero:您可以使用自动处理这些事情的资源对象(RAII),而不是定义这五个特殊成员函数。

这样的对象是某个类C的数据成员还是基类(子对象)并不关心:隐式声明的&amp;由编译器提供的C定义的特殊成员函数将调用此资源对象的特殊成员函数,这很可能就足够了。

提示:可以为特定示例提供更精确的答案

答案 2 :(得分:0)

你不能“覆盖”构造函数。它不是C ++词汇表中的术语。你可以覆盖一个函数,但只有它是虚函数。

通常,您不应该在任何正确编写的基类的子构造函数中做任何特殊操作。让每一代人都照顾好自己。