继承带有默认参数的构造函数?
Inheriting constructors w / wo their default arguments?
C++ 入门(第 5 版)第 629 页指出:
- 如果基础 class 构造函数具有默认参数,则不会继承这些参数。
我自己试过了,在我看来,编译器生成的派生构造函数似乎也具有与基本构造函数相同的默认参数。
这里有一个小测试:
#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 个成员的垃圾,而是得到与从 base 继承的构造函数的默认参数完全相同的值?
也在网上搜索了关于这方面的明确回应,但发现 none.
您对书中的引用不完整。
If a base-class constructor has default arguments (§6.5.1, p. 236), those arguments
are not inherited. Instead, the derived class gets multiple inherited constructors in
which each parameter with a default argument is successively omitted. For example, if
the base has a constructor with two parameters, the second of which has a default,
the derived class will obtain two constructors: one with both parameters (and no
default argument) and a second constructor with a single parameter corresponding to
the left-most, non-defaulted parameter in the base class
因此您的 Derived class 将具有 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} {}
所以你没有从基础class继承任何默认参数。
Derived D(5);
调用上面三个构造函数中的第一个,基础构造函数被调用为
Base(5)
Also note that the default, copy, and move constructors are not
inherited. These constructors are synthesized using the normal rules. An inherited
constructor is not treated as a user-defined constructor. Therefore, a class that
contains only inherited constructors will have a synthesized default constructor.
来自[class.inhctor]:
The
candidate set of inherited constructors from the class X named in the using-declaration consists of actual
constructors and notional constructors that result from the transformation of defaulted parameters and
ellipsis parameter specifications as follows:
— [...]
— for each non-template constructor of X that has at least one parameter with a default argument, the set
of constructors that results from omitting any ellipsis parameter specification and successively omitting
parameters with a default argument from the end of the parameter-type-list, and
— [...]
我们有两个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)
。
最终结果是一样的 - 只是我们到达那里的方式有点不同。
C++ 入门(第 5 版)第 629 页指出:
- 如果基础 class 构造函数具有默认参数,则不会继承这些参数。
我自己试过了,在我看来,编译器生成的派生构造函数似乎也具有与基本构造函数相同的默认参数。
这里有一个小测试:
#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 个成员的垃圾,而是得到与从 base 继承的构造函数的默认参数完全相同的值?
也在网上搜索了关于这方面的明确回应,但发现 none.
您对书中的引用不完整。
If a base-class constructor has default arguments (§6.5.1, p. 236), those arguments are not inherited. Instead, the derived class gets multiple inherited constructors in which each parameter with a default argument is successively omitted. For example, if the base has a constructor with two parameters, the second of which has a default, the derived class will obtain two constructors: one with both parameters (and no default argument) and a second constructor with a single parameter corresponding to the left-most, non-defaulted parameter in the base class
因此您的 Derived class 将具有 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} {}
所以你没有从基础class继承任何默认参数。
Derived D(5);
调用上面三个构造函数中的第一个,基础构造函数被调用为
Base(5)
Also note that the default, copy, and move constructors are not inherited. These constructors are synthesized using the normal rules. An inherited constructor is not treated as a user-defined constructor. Therefore, a class that contains only inherited constructors will have a synthesized default constructor.
来自[class.inhctor]:
The candidate set of inherited constructors from the class X named in the using-declaration consists of actual constructors and notional constructors that result from the transformation of defaulted parameters and ellipsis parameter specifications as follows:
— [...]
— for each non-template constructor of X that has at least one parameter with a default argument, the set of constructors that results from omitting any ellipsis parameter specification and successively omitting parameters with a default argument from the end of the parameter-type-list, and
— [...]
我们有两个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)
。
最终结果是一样的 - 只是我们到达那里的方式有点不同。