为什么要删除基类的默认复制并移动ctor和赋值

Why delete default copy and move ctor and assignment for base classes?

本文关键字:移动 ctor 赋值 复制 默认 删除 基类 为什么      更新时间:2023-10-16

为什么要删除基类的默认复制并移动ctor和赋值?

这是来自斯特劳斯特鲁普的书(第4版c++)。

通常基类是抽象的,所以你为什么要担心呢,当你甚至不能实例化它们的时候。

您试图避免的情况:

class A
{
};
class B : public A
{
};
class C : public A
{
int foo;
};
int main(int argc, char** argv)
{
A* c_ptr = new C();
A* b_ptr = new B();
*b_ptr = *c_ptr;//unless you explictly dissalow this, it can be done!
}

答案是双重的;一个是语义问题,另一个是C++中的实用性问题。

值类型是可互换的,特定的实例是不相关的,它们应该是可复制的和可赋值的,并且表现得像常规类型。示例可能包括特定日期、圆周率值、名称和颜色。

引用类型表示事物的实例;具体的例子是相关的,它不仅仅是对一件事的描述。从语义上讲,允许复制这些内容是没有意义的。示例可能包括一个人、一个文件、一个线程。

C++中多态的类型是引用类型;它们必须通过引用(或指针)传递,以保持正确的行为。在实践中,复制构造函数不是多态的;通过基引用进行复制可能会导致切片,从而导致行为的改变,这是对副本的一种非常糟糕的表示。引入一种虚拟方法来允许多态类型的"克隆"是非常流行的。

这个问题建议基类应该是不可复制和不可赋值的,但事实上,只有基类才打算在这种情况下以多态方式使用。

在某些情况下,类被设计为继承自,但它并不是被设计为循环使用的;例如boost::non-copyable和CRTP类。在这种情况下,防止从它们派生的类的实例通过引用基来持有也是有意义的;通常是通过将构造函数或析构函数中的一个或两个设置为受保护或私有来降低它们的可见性。这些类不需要虚拟析构函数。