2017-06-13 61 views
9
class A{ 

public: 
    A(){}; 

}; 

class B : public A{ 

public: 
    using A::A; 

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

}; 

B b; 

编译器(克++(5.4.0-6ubuntu1)/ C++ 11)显示“呼叫到B :: B没有匹配的功能()“并列出副本并将构造函数移动为候选项。如果我评论那些违约的人,那么它编译。这是什么原因?它们有什么区别,他们明确默认?如果那两条线不在那里,那么它们将会被默认设置。C++默认构造不继承与“使用”时,移动和复制本构造

+0

'using'不带所有的基构造函数。在某些情况下不会生成默认构造函数。 – Jarod42

+0

不确定,但是一旦你明确声明了一个构造函数(不管它是否为默认构造函数),编译器将不会自动为你生成一个构造函数 – user463035818

+0

请注意''使用A :: A;'不是这里问题的一部分:if你评论它,你会得到同样的错误。 –

回答

8

C++ 17之前,基类的默认构造函数不会inherited通过using

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

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

在此之前,缺省构造函数将不会从基类继承,因为复制/移动构造函数被提供,所以类B将不会是generated

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

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

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

    B() = default; 
}; 

代码编译与gcc8

+0

真的需要把'使用A :: A'放在那里吗?如果你忽略它并且保留'B()= default',它会有所作为吗? – petersohn

+0

@petersohn是的,它不是。你是对的。 – songyuanyao

5

如果声明任何构造函数的默认构造函数是不是implicitly generated,你可以通过添加= default它也产生它:

class B : public A { 

public: 

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

这与C++17改变(由other回答指出, )。

3

默认的构造函数不能被继承,标准明确地这样说。引用C++ 11 12.9 [class.inhctor]/3(重点煤矿)(*)

对于在候选集合中比没有一个构造 其他遗传构造的每个非模板构造参数或具有单个参数的复制/移动构造函数,构造函数隐含地声明为 ,具有相同的构造函数特性,除非在使用声明出现的类中存在具有相同 签名的用户声明构造函数。 ...

这意味着对于默认构造函数,正常规则适用,就好像using A::A;声明不存在一样。因此,任何其他构造函数声明(例如复制&移动构造函数)的出现都会导致默认构造函数不会被隐式声明。请注意,您可以轻松地添加回被拖欠明确它:

class B : public A{ 

public: 
    using A::A; 

    B() = default; 

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

}; 

(*)同样的措辞出现在C++ 14(n4140),在同一地点。我似乎无法找到C++ 1Z相当于措辞(通过n4582看)

+0

这是否改变了更新的标准? –

+0

@PasserBy我认为是这样的,12.9段不存在,因为(至少)n4582,这是(如果我没记错的话)C++ 1z的基础。 – Holt

+0

@霍尔特是的,我正在浏览标准,我没有看到类似于上面的报价。我确实看到这个,虽然'使用T :: T; //继承T类中的所有构造函数' –