是一个继承的默认构造函数,也是用户定义的

Is an inherited default constructor also user-defined?

本文关键字:构造函数 定义 用户 默认 继承 一个      更新时间:2023-10-16

Clang文档巧妙地解释了

如果类或结构没有用户定义的默认构造函数,则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"
}

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的想法并非如此。

UPDATE:根据@JesseGood关于0/1参数构造函数从不继承的回答,我尝试将Base构造函数更改为

Base(int b = 0, void* = nullptr): b_(b) {}

但是它不能解决Clang错误。

Clang是正确的。

关于const实例的相关文章来自8.5p7:

如果程序调用的对象的默认初始化const限定的类型T,T应为具有用户提供的类类型默认构造函数。

由于Base(): b_(0) {}是用户提供的,所以Base const b;是可以的。

下一个重要部分是12.9p3:

对于继承的候选集合中的每个非模板构造函数构造函数,而不是没有参数的构造函数或复制/移动具有单个参数的构造函数,构造函数是使用相同的构造函数特性隐式声明,除非中有一个用户声明的构造函数具有相同的签名出现using声明的类

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

这也意味着,基类中的默认构造函数、复制构造函数和移动构造函数是从不继承的。