删除复制构造函数会破坏继承的构造函数
Deleting copy constructor breaks inherited constructors
我正在尝试使用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);
}
也就是说,直到添加了注释所标记的行;因为那样的话,一切就都乱了:
> g++ -std=c++11 -o test test.cpp
test.cpp: In function ‘int main(int, char**)’:
test.cpp:18:11: error: no matching function for call to ‘Derived::Derived()’
Derived d1;
^
test.cpp:18:11: note: candidates are:
test.cpp:13:16: note: Derived::Derived(int)
using Base::Base;
^
test.cpp:13:16: note: candidate expects 1 argument, 0 provided
test.cpp:13:16: note: Derived::Derived(int, double)
test.cpp:13:16: note: candidate expects 2 arguments, 0 provided
似乎删除复制构造函数也以某种方式使Base
的默认构造函数不可访问。在谷歌上搜索这个问题没有找到任何有用的信息;SO建议这个问题,但据我所知,我没有在这个片段中使用复制初始化。有人能解释一下这里发生了什么吗?
(生成上述消息的编译器是GCC 4.8.2;但是,clang返回类似的错误消息。)
问题是用delete
标记复制构造函数使其用户声明的,这实际上删除了该类的默认构造函数(在您的示例中是Derived
)。这个行为可以在这个简单的代码中看到:
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()
。一般来说,using Base::Base
语句只是编译器生成的相应Derived(params): Base(params){}
的语法糖。
无论何时定义自定义构造函数,都需要显式地提供默认构造函数。例如
Derived::Derived() = default;
继承构造函数不会得到特殊的构造函数——empty、copy、move。这是因为你所要求的几乎总是一个坏主意。
检查:
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;
};
你真的希望derived(base const&)
存在吗?或者derived(base&&)
?两者都无望地分割derived
。
这些操作"意外"发生的危险这意味着如果你想要它们,你必须显式地引入它们。
copy/move/default函数,默认情况下,恰好只调用父版本,加上成员变量的函数。(通常)不需要从父节点继承它们。
但是,一旦您定义了=delete
、=default
或其中一个特殊的变量,编译器将停止生成其他的变量。所以如果你还想让它们留在这里,你必须把其他的设置为=default
- 具有相同名称的类的构造函数继承
- 多复制构造函数继承中的惊人行为
- CRTP 和复制/移动赋值/构造函数继承
- 复制构造函数继承动态分配的数组
- 无法从 c++ 中的构造函数继承
- 在构造函数继承中使用默认构造函数
- 构造函数继承和直接成员初始化
- C++ - 使用私有参数的构造函数继承
- 通过可变参数模板进行C++11构造函数继承
- C++11构造函数继承和不带参数的构造函数
- C++11 - 构造函数继承
- C++构造函数继承
- 使用 C++11 编译器的构造函数继承正在生成错误
- 选择性构造函数继承"Ambiguous resolution"错误
- 什么是构造函数继承
- C++对象中的构造函数继承与方法继承
- C++构造函数继承没有匹配的函数
- C++构造函数继承(从派生类调用构造函数)
- 模板构造函数继承的标准符合语法是什么
- C++构造函数继承错误