class A{
public:
A(){};
};
class B : public A{
public:
using A::A;
B(const B&) = default;
B( B&&) = default;
};
B b;
编译器(g ++(5.4.0-6ubuntu1)/ c ++ 11)说“没有用于调用B :: B()的匹配函数”,并将复制和移动构造函数列为候选。如果我评论那些默认的那些,那么它就会编译。是什么导致这个?它们明显违约有什么区别?如果不存在这两行,那么无论如何它们都会被默认。
答案 0 :(得分:8)
在C ++ 17之前,基类的默认构造函数不是inherited来自using
:
所有候选继承的构造函数都不是默认构造函数或复制/移动构造函数,并且其签名与派生类中的用户定义构造函数不匹配,在派生类中隐式声明。 (直到C ++ 17)
在C ++ 17之后,代码工作正常。
在此之前,默认构造函数不会从基类继承,并且对于类B
不会是generated,因为提供了复制/移动构造函数。
如果没有为类类型(struct,class或union)提供任何类型的用户声明的构造函数,编译器将始终将默认构造函数声明为其类的内联公共成员。
这就是为什么如果你评论复制/移动构造函数,它编译。您可以将该定义明确添加为C ++之前的17种解决方法。 e.g。
class B : public A {
public:
B(const B&) = default;
B( B&&) = default;
B() = default;
};
代码用gcc8编译。
答案 1 :(得分:5)
如果声明任何构造函数,则默认构造函数不是implicitly generated,您也可以通过为其添加= default
来生成它:
class B : public A {
public:
B() = default;
B(const B&) = default;
B( B&&) = default;
};
答案 2 :(得分:3)
默认构造函数不能被继承,标准明确地这样说。引用C ++ 11 12.9 [class.inhctor] / 3(强调我的)(*):
对于继承构造函数的候选集中的每个非模板构造函数,而不是构造函数 没有参数或具有单个参数的复制/移动构造函数,构造函数是隐式的 声明具有相同的构造函数特征,除非有一个用户声明的构造函数具有相同的构造函数 出现using声明的类中的签名。 ...
这意味着对于默认构造函数,正常规则适用,就像using A::A;
声明不存在一样。因此,任何其他构造函数声明(例如copy和amp; move构造函数)的存在都会导致默认构造函数不被隐式声明。请注意,您可以通过明确默认将其轻松添加回来:
class B : public A{
public:
using A::A;
B() = default;
B(const B&) = default;
B( B&&) = default;
};
(*)在C ++ 14(n4140)中,在同一位置存在相同的措辞。我似乎无法在C ++ 1z中找到相同的措辞(通过n4582查看)