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 MSVC Derived d0; works on all three. 【参考方案1】:

“神奇”在于您不小心使用了聚合初始化。在 C++20(而不是之前)中,您可以通过使用括号而不是花括号来调用聚合初始化,只要不会调用实际的构造函数(如复制/移动构造函数)。这样做是为了允许间接构造类型(emplaceoptional 的就地构造函数、make_shared/unique 等)来处理聚合类型。

您的类型Derived 是一个聚合,因为它没有用户提供的构造函数和一个子对象(基类)。因此,您使用构造函数语法将调用聚合初始化,第一个聚合成员是基类。可以从int 构造(顺便说一句,除非它们是复制/移动构造函数,否则不从单个参数explicit 创建构造函数通常是不好的形式)。

一般来说,除非您打算创建一个聚合(即:类型只是一个任意的值束),否则派生类应该有构造函数。我不记得我何时编写了一个没有也至少有一个构造函数的派生类。如果您希望派生类拥有基类构造函数,那么无论何时您都应该明确说明这一点。没有明确的声明,构造函数不会被继承。

【讨论】:

【参考方案2】:

诀窍是使用派生构造函数。

Derived::Derived(int a, int b) : Base(a, b) 
    ...

非静态成员也可以这样初始化。

【讨论】:

问题的重点是他不想这样做 OP 已经知道了。问题问为什么第二个 sn-p 可以编译,为什么只能在 C++20 中编译。

以上是关于C++ 为啥基类/结构构造函数不能有多个参数可以从派生中隐式调用?的主要内容,如果未能解决你的问题,请参考以下文章

C++ 构造函数不能是虚函数,基类析构函数应该为虚函数

C++中,继承时,创建子类对象,能否在子类构造函数初始化列表里调用基类构造函数?

C++基类和派生类的构造函数

C++中子类从基类都继承啥?

基类构造函数参数值[重复]

如何在 C++ 中调用基类的参数化构造函数?