继承的默认构造函数是否也是用户定义的?

Tem*_*Rex 12 c++ g++ clang default-constructor c++11

锵文档整齐地解释说,

如果类或结构没有用户定义的默认构造函数,C++不允许您默认构造它的const实例([dcl.init],p9)

以下代码具有这样的用户定义的默认构造函数Base,但g ++和Clang不同意默认构造函数是否Derived是用户定义的,即使Derived它显式继承了所有Base构造函数(使用新的C++ 11继承构造函数)

#include <iostream>

class Base
{
public:
    Base(): b_(0) {}  // look! user-defined default constructor
    void print() const { std::cout << b_ << "\n"; }
private:
    int b_;
};

class Derived
:
    public Base
{
    using Base::Base; // does this constitute a user-defined default constructor?
};

int main()
{
    Base const b;
    b.print();    // 0 for g++ & CLang

    Derived const d;
    d.print();    // 0 for g++, Clang: "default initialization of an object of const type 'const Derived' requires a user-provided default constructor"
}
Run Code Online (Sandbox Code Playgroud)

g ++ 4.8很高兴接受这段代码,但Clang 3.3却没有.标准说什么?

注意:没有用户定义的默认构造函数Base,g ++ 4.8和Clang 3.3都不接受Base const b;(例如g ++ 4.7.2之前接受过).鉴于g ++知道规则,我认为这意味着g ++将默认构造函数Derived视为用户定义的.但Clang 3.3认为不然.

更新:根据@JesseGood的回答,0/1参数构造函数永远不会被继承,我尝试将Base构造函数更改为

Base(int b = 0, void* = nullptr): b_(b) {}
Run Code Online (Sandbox Code Playgroud)

但它无法解决Clang错误.

Jes*_*ood 7

铿锵是对的.

关于const实例的相关段落来自8.5p7:

如果程序要求对const限定类型T的对象进行默认初始化,则T应为具有用户提供的 默认构造函数的类类型.

由于Base(): b_(0) {}是用户提供的,Base const b;很好.

下一个重要部分是12.9p3:

对于除了没有参数的构造函数或具有单个参数的复制/移动构造函数之外的候选继承构造函数集中的每个非模板构造函数,构造函数隐式声明具有相同的构造函数特征,除非存在用户声明的构造函数出现using声明的类中的相同签名

这里重要的部分是粗体文本.我相信这排除了你的情况,因为它Base()是一个没有参数的构造函数.这意味着Derived没有用户提供的默认构造函数(尽管仍然隐式声明了一个).

这也意味着永远不会继承基类的默认,复制和移动构造函数.

  • @rhalbersma:是的,它仍然算作没有参数的非继承的ctor.但是,Base(int)`和`Base(int,void*)`是继承的.(但是,默认参数不会被继承). (2认同)