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

时间:2014-01-16 22:04:10

标签: c++ c++11

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

这是来自Stroustrup的书(第4版c ++)。

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

2 个答案:

答案 0 :(得分:6)

您要避免的情况:

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

答案 1 :(得分:0)

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

值类型是可互换的,特定实例不相关,它们应该是可复制和可分配的,并且像常规类型一样。示例可能包括特定日期,pi的值,名称,颜色。

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

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

这个问题表明基类应该是不可复制的和不可赋值的,但实际上,只有在适用的情况下才能以多态方式使用基类。

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