继承构造函数w/wo默认参数?

Mug*_*rel 7 c++ inheritance constructor default-arguments c++11

C++ Primer(第5版)第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;
}
Run Code Online (Sandbox Code Playgroud)

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


那么我们是否继承了继承构造函数的默认参数?
如果没有,为什么我没有为最后2个成员获取垃圾,但是与从base继承的构造函数的默认argumuments具有相同的确切值?
还在互联网上搜索了关于此的明确答复,但没有找到.

Elo*_*eth 8

你对这本书的引用并不完整.

如果基类构造函数具有默认参数(第6.5.1节,第236页),则不会继承这些参数.相反,派生类获取多个继承的构造函数,其中连续省略具有默认参数的每个参数.例如,如果base有一个带有两个参数的构造函数,第二个参数有一个默认值,派生类将获得两个构造函数:一个带有两个参数(并且没有默认参数),另一个构造函数带有一个参数对应于基类中最左侧的非默认参数

因此,您的Derived类将具有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} {}
Run Code Online (Sandbox Code Playgroud)

因此,您不会从基类继承任何默认参数.

Derived D(5);
Run Code Online (Sandbox Code Playgroud)

调用上面三个构造函数中的第一个,并调用基础构造函数

Base(5)
Run Code Online (Sandbox Code Playgroud)

另请注意,默认,复制和移动构造函数不会被继承.这些构造函数使用常规规则合成.继承的构造函数不被视为用户定义的构造函数.因此,只包含继承的构造函数的类将具有合成的默认构造函数.

  • 因为Base默认参数没有消失.他们还在那里.而Base(5)真的称Base(5,88,99) (2认同)

Bar*_*rry 6

来自[class.inhctor]:

来自使用声明中命名的类X的继承构造函数的候选集由实际构造函数和由默认参数和省略号参数规范的转换产生的名义构造函数组成,如下所示:
- [...]
- 对于每个非模板X的构造函数,至少有一个参数带有一个默认参数,一组构造函数,它们省略了任何省略号参数规范,并从参数类型列表的末尾依次省略了带参数的参数,并且
- [.. ]

我们有两个非模板构造函数Base.Base引入候选人的默认构造函数:

Derived() : Base() { }
Run Code Online (Sandbox Code Playgroud)

而另一个构造函数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) { }
Run Code Online (Sandbox Code Playgroud)

默认参数不会被继承 - 我们只为每个参数数量获得一个不同的构造函数.所以Derived(5)只是打电话Base(5),而不是Base(5, 88, 99).

最终的结果是一样的 - 我们如何到达那里有点不同.