继承带有默认实参的构造函数

Inheriting constructors w / wo their default arguments?

本文关键字:构造函数 实参 默认 继承      更新时间:2023-10-16

c++ Primer (5th edition)第629页说明:

  • 如果基类构造函数有默认实参,这些实参不会被继承。

我为自己尝试了这个,对我来说,编译器生成的派生构造函数似乎也具有与基构造函数相同的默认参数。

这里有一个小测试:

#include <iostream>
struct Base
{
    Base() = default;
    Base(int x_, int y_ = 88, int z_ = 99)
        : x(x_), y(y_), z(z_) {}
    virtual void debug() const 
    { std::cout << "nx - " << x << ", y - " << y << ", z - " << z << 'n'; } 
private:
    int x, y, z;
};
struct Derived : Base
{
    using Base::Base;
};
int main() {
    Base B(1);
    B.debug();         // x - 1, y - 88, z - 99
    Derived D(5);
    D.debug();         // x - 5, y - 88, z - 99
    return 0;
}

(你可以在这里运行- http://coliru.stacked-crooked.com/a/26cbb85757c1f021)


那么我们是否也继承了继承构造函数的默认参数呢?
如果不是,为什么我没有得到垃圾的最后2个成员,但相同的值作为默认的构造函数从基继承的参数?
我也在网上搜索了一个明确的回应,但没有找到。

你在书中引用的内容不完整。

如果基类构造函数有默认实参(第6.5.1节),则这些实参不是遗传的。派生类中有多个继承构造函数每个带有默认实参的形参被依次省略。例如,如果基类有一个带两个参数的构造函数,第二个参数有一个默认值,派生类将获得两个构造函数:一个具有两个参数(没有参数)默认实参)和第二个构造函数,其单个形参对应于基类

中最左边的非默认形参

所以你的派生类将有3个继承的构造函数签名:

Derived (int x): Base{x} {}
Derived (int x, int y): Base{x, y} {}
Derived (int x, int y, int z): Base{x, y, z} {}

所以你是从基类继承任何默认参数。

Derived D(5);

调用上述三个构造函数中的第一个,基构造函数像

一样调用
Base(5)

还要注意default、copy和move构造函数不是继承。这些构造函数是使用常规规则合成的。一种遗传构造函数不被视为用户定义的构造函数。因此,一个类只包含继承的构造函数将有一个合成的默认构造函数。

From [class. info]:

从using声明中指定的类X继承的候选构造函数集包括构造函数和概念构造函数,由默认参数和省略号参数规范如下:
- - - - - -[…]
-对于X的每个至少有一个带默认实参形参的非模板构造函数,set省略任何省略号参数说明和连续省略所导致的构造函数形参类型列表末尾带有默认实参的形参,以及
- - - - - -[…]

我们有两个Base的非模板构造函数。Base的默认构造函数引入了候选对象:

Derived() : Base() { }

Base的另一个构造函数为每一个依次省略的参数引入一个候选参数。即:

Derived(int x, int y, int z) : Base(x, y, z) { }
Derived(int x, int y)        : Base(x, y) { }
Derived(int x)               : Base(x) { }

默认实参是而不是继承——我们只是为每个数量的实参获得不同的构造函数。所以Derived(5)只是调用Base(5),而不是Base(5, 88, 99)

最终结果是一样的——只是我们到达那里的方式有点不同。