C++ 为啥基类/结构构造函数不能有多个参数可以从派生中隐式调用?
Posted
技术标签:
【中文标题】C++ 为啥基类/结构构造函数不能有多个参数可以从派生中隐式调用?【英文标题】:C++ Why base class/struct constructor can't have more than one argument to be implicitly callable from derived?C++ 为什么基类/结构构造函数不能有多个参数可以从派生中隐式调用? 【发布时间】:2021-01-27 13:05:37 【问题描述】:为什么这行不通:
struct Base
Base(int a, int b)
;
struct Derived: Base
// using Base::Base; // unless I add this
;
int main()
Derived d(0, 0);
虽然这样可以:
struct Base
Base(int a)
;
struct Derived: Base
// using Base::Base; // without this line
;
int main()
Derived d(0);
注意:C++20 GCC 10.2(第二个示例也不适用于 C++17)
C++20 中第二个例子背后的魔法是什么?
【问题讨论】:
GCC 接受它:wandbox.org/permlink/swiVgY4nUIrgju1I,但 clang 不接受:wandbox.org/permlink/AkCbQT8aJo17J9Lh。我想这是 GCC 方面的错误。 @RoQuOTriX 事情是我只想要一个 (int, int) 构造函数。在您的示例中,有三个。我正在使用 gcc 10.2。 @Cansisti 我犯了另一个错误,对不起 @Yksisarvinen It also works on MSVCDerived d0;
works on all three.
【参考方案1】:
“神奇”在于您不小心使用了聚合初始化。在 C++20(而不是之前)中,您可以通过使用括号而不是花括号来调用聚合初始化,只要不会调用实际的构造函数(如复制/移动构造函数)。这样做是为了允许间接构造类型(emplace
、optional
的就地构造函数、make_shared/unique
等)来处理聚合类型。
您的类型Derived
是一个聚合,因为它没有用户提供的构造函数和一个子对象(基类)。因此,您使用构造函数语法将调用聚合初始化,第一个聚合成员是基类。可以从int
构造(顺便说一句,除非它们是复制/移动构造函数,否则不从单个参数explicit
创建构造函数通常是不好的形式)。
一般来说,除非您打算创建一个聚合(即:类型只是一个任意的值束),否则派生类应该有构造函数。我不记得我何时编写了一个没有也至少有一个构造函数的派生类。如果您希望派生类拥有基类构造函数,那么无论何时您都应该明确说明这一点。没有明确的声明,构造函数不会被继承。
【讨论】:
【参考方案2】:诀窍是使用派生构造函数。
Derived::Derived(int a, int b) : Base(a, b)
...
非静态成员也可以这样初始化。
【讨论】:
问题的重点是他不想这样做 OP 已经知道了。问题问为什么第二个 sn-p 可以编译,为什么只能在 C++20 中编译。以上是关于C++ 为啥基类/结构构造函数不能有多个参数可以从派生中隐式调用?的主要内容,如果未能解决你的问题,请参考以下文章