标准说(§12.6.2/101,重点是我的):
如果给定的非静态数据成员同时具有默认成员初始化器和 mem-initializer,则初始化
mem-initializer 指定的执行,非静态数据成员的默认成员初始化器被忽略。 [例子:给定
struct A {
int i = /* some integer expression with side effects */ ;
A(int arg) : i(arg) { }
// ...
};
A(int) 构造函数将简单地将i 初始化为arg 的值,并且i 的默认成员初始化程序中的副作用不会发生。 ——结束示例]
http://coliru.stacked-crooked.com/ 使用不产生警告但结果相同的 g++:Base 未使用 50 或 23 初始化,而是使用 0。您可以通过在mymy 之前添加另一个属性来获得更奇怪的行为:
class Derived: public Base {
public:
Derived() : Base(mymy), mymymy(mymy), mymy(23) {
std::cout << "Derived:" << mymy << std::endl;
std::cout << "Derived:" << mymymy << std::endl;
}
int mymymy;
const int mymy = 50;
};
来自coliru的输出:
Base:4197208
Derived:23
Derived:4197208
Main:23
但是如果你在mymy之后添加一个属性:
class Derived : public Base {
public:
Derived() : Base(mymy), mymy(23) {
std::cout << "Derived:" << mymy << std::endl;
std::cout << "Derived:" << mymymy << std::endl;
}
const int mymy = 50;
int mymymy= mymy;
};
将使用您在构造函数的 member-initializer-list 中提供的值:
Base:0
Derived:23
Derived:23
Main:23
关于const 限定条件:您始终可以在构造函数的member-list-initializer 中初始化const 成员(这是唯一可以与默认成员初始化器一起初始化它们的地方)。
我不知道标准中是否有更明确的引用,但 §12.6.2/71 (虽然这个例子很明确):
mem-initializer 中的 expression-list 或 braced-init-list 用于初始化指定的子对象(或者,在委托构造函数的情况下,完整的类对象)根据 8.5 的初始化规则进行直接初始化。
[ 例子:
struct B1 { B1(int); /* ... */ };
struct B2 { B2(int); /* ... */ };
struct D : B1, B2 {
D(int);
B1 b;
const int c;
};
D::D(int a) : B2(a+1), B1(a+2), c(a+3), b(a+4)
{ /* ... */ }
D d(10);
——结束示例 ]
1 最新的 C++17 标准草案 (N4594)。