C++ 继承的默认构造函数也是用户定义的吗?
报告清楚地解释了这一点C++ 继承的默认构造函数也是用户定义的吗?,c++,c++11,g++,clang,default-constructor,C++,C++11,G++,Clang,Default Constructor,报告清楚地解释了这一点 如果类或结构没有用户定义的默认构造函数,C++ 不允许默认构造它的常量实例,如 这([dcl.init],第9页) 下面的代码为Base提供了这样一个用户定义的默认构造函数,但是g++和Clang不同意Derived的默认构造函数是否是用户定义的,即使Derived确实显式继承了所有Base构造函数(使用) 但它不能解决叮当声错误。叮当声是正确的 有关const实例的相关段落来自8.5p7: 如果程序调用 const合格类型T,T应为用户提供的类类型 默认构造函数 由于B
如果类或结构没有用户定义的默认构造函数,C++ 不允许默认构造它的常量实例,如 这([dcl.init],第9页)
下面的代码为Base
提供了这样一个用户定义的默认构造函数,但是g++和Clang不同意Derived
的默认构造函数是否是用户定义的,即使Derived
确实显式继承了所有Base
构造函数(使用)
但它不能解决叮当声错误。叮当声是正确的
有关const实例的相关段落来自8.5p7:
如果程序调用
const合格类型T,T应为用户提供的类类型
默认构造函数
由于Base():b_0{}
是用户提供的,Base const b代码>很好
下一个重要部分是12.9p3:
对于继承的候选集合中的每个非模板构造函数
构造函数而不是没有参数的构造函数或
复制/移动构造函数如果只有一个参数,则
使用相同的构造函数特征隐式声明,除非
中有一个具有相同签名的用户声明构造函数
类中显示using声明的位置
这里的重要部分是粗体文本。我认为这排除了您的情况,因为Base()
是一个没有参数的构造函数。这意味着派生的
没有用户提供的默认构造函数(尽管仍然隐式声明了一个)
这也意味着基类中的默认、复制和移动构造函数是继承的。你说得对,我误解了这个问题。+1谢谢你的回答。如果我将Base
构造函数签名更改为Base(int b=0,void*=nullptr):b_b(b){}
,则默认构造函数将被抑制。但是,Clang仍然在派生的上给出错误(并且g++接受它)。具有2个默认参数的构造函数是否也算作没有参数的非继承构造函数?@rhalbersma:是的,它仍然算作没有参数的非继承构造函数<代码>基(int)
和基(int,void*)
是继承的。(但是,默认参数不是继承的)。如果我正确理解12.9p3部分,正确的解释(对于C++11)将是完全忽略使用Base::Base
,因为唯一可以继承的构造函数没有参数,所以它不是。因此,即使没有const资格,它也不会起作用。奇怪的是,文本标准没有说明为什么默认结构在遗产中受到歧视。此外,该子句似乎已被删除,因为:继承构造函数并同时声明构造函数的类(因此没有隐式默认值)无法使用g++-4.8编译无参数声明,但可以使用g++-7.3
#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"
}
Base(int b = 0, void* = nullptr): b_(b) {}