C++ 成员初始值设定项未命名非静态数据成员或基类
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18479295/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
member initializer does not name a non-static data member or base class
提问by Steven Lu
I'm having a hard time finding hits on google for this.
我很难在谷歌上找到这个。
struct a {
float m_x;
float m_z;
public:
a(float x): m_x(x) {}
};
class b : public a {
b(float z): m_z(z) {}
};
On clang 3.2:
在叮当 3.2 上:
error: member initializer 'm_z' does not name a non-static data member or base class
b(float z): m_z(z) {}
回答by 4pie0
No you cannot initialize base class members from initializer list directly. This is because order of initialization proceeds in this way
不,您不能直接从初始化列表初始化基类成员。这是因为初始化的顺序是这样进行的
C++ Standard n3337 §12.6.2/10
C++ 标准 n3337 §12.6.2/10
In a non-delegating constructor, initialization proceeds in the following order:
— First, and only for the constructor of the most derived class (1.8), virtual base classes are initialized in the order they appear on a depth-first left-to-right traversal of the directed acyclic graph of base classes, where “left-to-right” is the order of appearance of the base classes in the derived class base-specifier-list.
— Then, direct base classes are initializedin declaration order as they appear in the base-specifier-list (regardless of the order of the mem-initializers).
— Then, non-static data members are initializedin the order they were declared in the class definition (again regardless of the order of the mem-initializers).
— Finally, the compound-statement of the constructor body is executed.
[ Note: The declaration order is mandated to ensure that base and member subobjects are destroyed in the reverse order of initialization. — end note ]
在非委托构造函数中,初始化按以下顺序进行:
— 首先,仅对于最派生类 (1.8) 的构造函数,虚拟基类按照它们在基类的有向无环图的深度优先从左到右遍历中出现的顺序进行初始化,其中“左-to-right”是派生类基类说明符列表中基类的出现顺序。
—然后,直接基类按照它们出现在基说明符列表中的声明顺序进行初始化(不管内存初始化器的顺序如何)。
—然后,非静态数据成员按照它们在类定义中声明的顺序进行初始化(同样与 mem 初始化程序的顺序无关)。
—最后,执行构造函数体的复合语句。
[注意:声明顺序是为了确保基类和成员子对象以与初始化相反的顺序销毁。— 尾注 ]
So you can specify a constructor in a base class (it can be protected) and use that one in initialization list of derived class (should be preferred) or you can assignto a base class member in derived class ctor body (different behaviour, different effect and also less efficient - you are assigning to default initialized (already has value) member).
所以你可以在基类中指定一个构造函数(它可以被保护)并在派生类的初始化列表中使用它(应该是首选),或者你可以分配给派生类构造函数主体中的基类成员(不同的行为,不同的效果和效率也较低 - 您正在分配给默认初始化(已具有值)成员)。
In the former case you might write it this way:
在前一种情况下,您可以这样编写:
struct A {
float m_x;
float m_z;
A(){}
protected:
A(float x): m_x(x) {}
};
class B : public A {
public:
B(float z) : A(z) {}
// alternatively
// B(float z) {
// m_x = z;
// }
};
int main(){
B b(1);
return 0;
}