请注意,就像 Jonathan Wakely 提到的那样,C++17 已经改变了这种行为。现在参数列表中的默认参数会被继承。
也就是说,如果我们在一个名为Base的类中有如下构造函数,
struct Base {
Base(int a, int b, int c = 1, int d = 2, int e = 3) {}
};
那么对于上面的构造函数,这些是在 C++11/C++14 中“注入”到派生类中的相应构造函数:
struct Derived : Base {
using Base::Base;
/*
C++11/C++14:
Derived::Derived(int a, int b) : Base(a, b) {}
Derived::Derived(int a, int b, int c) : Base(a, b, c) {}
Derived::Derived(int a, int b, int c, int d) : Base(a, b, c, d) {}
Derived::Derived(int a, int b, int c, int d, int e) : Base(a, b, c, d, e) {}
*/
};
而 C++17 中的那个现在要简单得多:
struct Derived : Base {
using Base::Base;
/*
C++17:
Derived::Derived(int a, int b, int c = 1, int d = 2, int e = 3) : Base(a, b, c, d, e) {}
*/
};
为什么我认为这是:
基于关于继承构造函数的cppreference.com page 和介绍更改(P0136R1) 的论文,整个[class.inhctor]\1 小节指定了如何拆分继承的构造函数并将其“注入”到派生类中。 (实际上整个 [class.inhctor] 部分已被删除)。然后它被 C++17 中[namespace.udecl]\16 中的一个简单规则替换为(强调我的):
为了重载决议,由 using 声明引入派生的函数
类被视为派生类的成员。特别是隐含的 this 参数
应将其视为指向派生类而不是基类的指针。这对
函数的类型,并且在所有其他方面,该函数仍然是基类的成员。同样地,
由 using 声明引入的构造函数被视为好像它们是
派生类查找派生类的构造函数时(6.4.3.1)或形成一组重载
候选人(16.3.1.3、16.3.1.4、16.3.1.7)。如果选择这样的构造函数来执行初始化
类类型的对象,除了构造函数源自的基类之外的所有子对象都是
隐式初始化 (15.6.3)。
所以参数列表现在完全“继承”了。确实,这是我在 GCC 7.2 中使用符合 P0136R1 的 CLion 的经验,而我的不符合 P0136R1 的 Visual Studio 2017 (15.6) 显示了较旧的 4 个构造函数,并且删除了默认参数。