当移动和复制构造函数存在时,C++默认构造函数不会使用"using"继承

Ady*_*Ady 9 c++ constructor language-lawyer c++11 c++17

class A{

public:
    A(){};

};

class B : public A{

public:
    using A::A;

    B(const B&) =   default;
    B(      B&&) =  default;

};

B b;
Run Code Online (Sandbox Code Playgroud)

编译器(g ++(5.4.0-6ubuntu1)/ c ++ 11)说"没有用于调用B :: B()的匹配函数",并将复制和移动构造函数列为候选.如果我评论那些默认的那些,那么它就会编译.是什么导致这个?它们明显违约有什么区别?如果那两条线不在那里,他们无论如何都会被拖欠.

son*_*yao 8

在C++ 17之前,基类的默认构造函数不会通过以下方式继承using:

所有候选继承的构造函数都不是默认构造函数或复制/移动构造函数,并且其签名与派生类中的用户定义构造函数不匹配,在派生类中隐式声明.(直到C++ 17)

在C++ 17之后,代码工作正常.

在此之前,默认构造函数不会从基类继承,也不会为类生成,B因为提供了复制/移动构造函数.

如果没有为类类型(struct,class或union)提供任何类型的用户声明的构造函数,则编译器将始终将默认构造函数声明为其类的内联公共成员.

这就是为什么如果你评论复制/移动构造函数,它编译.您可以将该定义明确添加为C++之前的17种解决方法.例如

class B : public A {
public:
    B(const B&) =   default;
    B(      B&&) =  default;

    B() = default;
};
Run Code Online (Sandbox Code Playgroud)

代码用gcc8编译.


gau*_*teh 5

如果声明任何构造函数,则不会隐式生成默认构造函数,您也可以通过添加= defaultfor 来生成它:

class B : public A {

public:

    B() = default;
    B(const B&) =   default;
    B(      B&&) =  default;
};
Run Code Online (Sandbox Code Playgroud)

这已经随着C++ 17而改变了(正如其他答案所指出的那样).