C++ 删除复制构造函数会中断继承的构造函数

C++ 删除复制构造函数会中断继承的构造函数,c++,c++11,inheritance,constructor,copy-constructor,C++,C++11,Inheritance,Constructor,Copy Constructor,我试图使用C++11的构造函数继承特性。以下代码片段(从某处复制,我不记得是从哪里复制的)完全可以正常工作: #include <iostream> struct Base { Base() : Base(0) {} Base(int a) : Base(a, 0) {} Base(int a, double b) { std::cout << "Base(" << a << "," << b << ")" &

我试图使用C++11的构造函数继承特性。以下代码片段(从某处复制,我不记得是从哪里复制的)完全可以正常工作:

#include <iostream>

struct Base {
  Base() : Base(0) {}
  Base(int a) : Base(a, 0) {}
  Base(int a, double b) { std::cout << "Base(" << a << "," << b << ")" << std::endl; }
};

struct Derived : Base {
  using Base::Base;
  Derived(const Derived& that) = delete;  // This line is the culprit
};

int main(int argc, char* argv[]) {
  Derived d1;
  Derived d2(42);
  Derived d3(42, 3.14);
}
似乎删除复制构造函数也会使
Base
中的默认构造函数无法访问。谷歌搜索这个问题并没有带来任何有用的东西;建议如此,但据我所知,我在这个代码段中不使用复制初始化。有人能解释一下这里发生了什么事吗


(生成上述消息的编译器是GCC 4.8.2;但是,clang会返回类似的错误消息。)

问题是,将副本构造函数标记为
delete
会使用户声明,这实际上会删除该类的默认构造函数(在您的示例中是
派生的
)。这种行为可以在以下简单代码中看到:

struct X
{
    X(const X&) = delete; // now the default constructor is not defined anymore
};

int main() 
{
    X x; // cannot construct X, default constructor is inaccessible 
}
附带说明:即使继承了
Base::Base()
,编译器也会这样看
Derived():Base(){}
。但是
Derived
被删除,因此它不能真正调用
Base::Base()
。通常,使用Base::Base语句的
只是相应编译器生成的
派生(params):Base(params){}

的语法糖,无论何时定义自定义构造函数,都需要显式提供默认构造函数。即

Derived::Derived() = default;

继承构造函数不会得到特殊的构造函数——空、复制、移动。这是因为你所要求的几乎总是一个坏主意


检查:

struct base {
  std::vector<int> data;
  base(base const&)=default;
  base(base&&)=default;
  base(size_t n):data(n) {}
  base()=default;
};

struct derived:base {
  using base::base;
  std::vector<char> more_data;
};
struct base{
std::矢量数据;
基本(基本常数&)=默认值;
基本值(基本值&)=默认值;
基(大小n):数据(n){
base()=默认值;
};
派生结构:基{
使用base::base;
std::向量更多的数据;
};
您真的希望
派生(基常量&)
存在吗?或
base(base&&)
?两者都会毫无希望地分割
派生的

这些操作“意外”发生的危险意味着,如果需要,您必须明确地引入它们


默认情况下,copy/move/default ctors恰好只调用父版本以及成员变量的ctors。没有必要(通常)从父母那里继承它们


但是,一旦
=delete
=default
或定义了其中一个特殊的构造函数,编译器就会停止生成其他构造函数。因此,如果您仍希望其他构造函数继续存在,则必须
=default

默认构造函数不是继承的。t.C。为什么呢在
导出的d1中行,我清楚地看到调用了
Base()
。@T.C.用词有误导性。当然,构造函数是继承的——否则,您将无法从派生类调用它们。它只是用于不同的类。这是我丢失的链接。从来没有想过删除某些东西会被视为“定制”它。谢谢@DavidNemeskey是的,它确实很令人困惑,但它就是这样工作的。标准术语是用户声明的。谢谢您的解释。即使
=default
也算作用户声明?@DavidNemeskey否。首先,因为我很邋遢。其次,因为user-declared是标准中定义的一个短语(我相信),我避免使用这些短语,因为它们具有谨慎的技术含义。但是
=default
可能会产生一些影响--如果您
=default
复制扇区,移动扇区将被抑制,反之亦然。对于默认值为空的构造函数,情况并非如此。