我正在尝试使用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建议this issue,但据我了解,我不在此代码段中使用复制初始化。有人可以对这里发生的事情有所了解吗?
(生成上述消息的编译器是GCC 4.8.2;但是,clang返回类似的错误消息。)
答案 0 :(得分:11)
问题是使用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){}
的语法糖。
答案 1 :(得分:4)
每当定义自定义构造函数时,都需要显式提供默认构造函数。即。
Derived::Derived() = default;
答案 2 :(得分:4)
继承构造函数并不能获得特殊的构造函数 - 空,复制,移动。这是因为你要求字面意思几乎总是一个坏主意。
检查:
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&)
存在吗?还是base(base&&)
?两者都无可救药地切片derived
。
这些操作发生的危险&#34;意外&#34;意味着你必须明确地将它们带入。
默认情况下,复制/移动/默认ctors恰好只调用父版本,加上成员变量的ctors。 (通常)不需要从父母那里继承它们。
但是,一旦你=delete
,=default
或定义其中一个特殊ctors,其他的就停止由编译器生成。所以你必须=default
其他的,如果你仍然希望他们坚持下去。