成员初始值设定项不命名非静态数据成员或基类

Ste*_* Lu 40 c++ clang c++11

我很难在Google上找到点击率.

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) {}
};
Run Code Online (Sandbox Code Playgroud)

在铿锵3.2:

error: member initializer 'm_z' does not name a non-static data member or base class
    b(float z): m_z(z) {}
Run Code Online (Sandbox Code Playgroud)

4pi*_*ie0 45

不,您无法直接从初始化列表初始化基类成员.这是因为初始化顺序以这种方式进行

C++标准n3337 § 12.6.2/10

在非委托构造函数中,初始化按以下顺序进行:

- 首先,仅对于派生程度最高的类(1.8)的构造函数,虚拟基类按照它们出现在基类的有向无环图的深度优先从左到右遍历的顺序进行初始化,其中"左" -to-right"是派生类base-specifier-list中基类出现的顺序.

- 然后,直接基类按声明顺序初始化,因为它们出现在base-specifier-list中(无论mem-initializers的顺序如何).

- 然后,非静态数据成员按照它们在类定义中声明的顺序进行初始化(同样不管mem-initializers的顺序如何).

- 最后,执行构造函数体的复合语句.

[注意:声明顺序的作用是确保以初始化的相反顺序销毁基础和成员子对象. - 结束说明]

因此,您可以在基类中指定构造函数(它可以受到保护)并在派生类的初始化列表中使用该构造函数(应该是首选),或者您可以在派生类ctor体中指定基类成员(不同的行为,不同效果也效率较低 - 您正在分配默认初始化(已有值)成员).

在前一种情况下,您可以这样写:

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;
}
Run Code Online (Sandbox Code Playgroud)

  • 您的代码示例是错误的:OP意味着执行“m_z = z”,而不是“m_x = z”,当然,在这种情况下“A(z)”将是错误的(这也意味着“m_z”未初始化在 A 对象中并且“m_x”未在 B 对象中初始化)。 (3认同)