为什么编译器(clang)抱怨mymy
未初始化,当我特意告诉它是一个常量值时,持有50.为什么它允许我将它改为23 ..当我还告诉他不变的时候?
#include <iostream>
class Base
{
public:
Base(int y) : my(y) {std::cout << "Base:" << my << std::endl;}
private:
int my;
};
class Derived : public Base
{
public:
Derived() : Base(mymy), mymy(23) {std::cout << "Derived:" << mymy << std::endl;}
private:
const int mymy = 50;
};
int main()
{
Derived a;
}
奇怪的是,coliru没有点击就编译了。 http://coliru.stacked-crooked.com/a/63629c2d99bf6f43(是的,我知道将其更改为static
将解决此问题)
答案 0 :(得分:4)
标准说(§12.6.2/ 10 1 ,重点是我的):
如果给定的非静态数据成员同时具有默认成员初始值设定项和 mem-initializer ,则初始化 执行 mem-initializer 指定,忽略非静态数据成员的默认成员初始值设定项。 [示例:给定
struct A { int i = /* some integer expression with side effects */ ; A(int arg) : i(arg) { } // ... };
A(int)
构造函数只会将i
初始化为arg
的值,并且i
的默认成员初始化程序中的副作用将不会发生。 -end example ]
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/ 7 1 (虽然这个例子非常明确):
mem-initializer 中的表达式列表或 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)。
答案 1 :(得分:3)
如果使用ctor初始化程序,则忽略类初始化。
考虑使用参数mymy
Derived() : Base(mymy), mymy(23) {std::cout << "Derived:" << mymy << std::endl;}
不正确,因为派生类的数据成员尚未初始化。