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

时间:2013-08-28 04:08:16

标签: c++ c++11 clang

我很难在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) {}
};

on clang 3.2:

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

1 个答案:

答案 0 :(得分:39)

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

C ++标准版n3337 § 12.6.2 / 10

  

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

     

- 首先,仅适用于最多的构造函数   派生类(1.8),虚拟基类按顺序初始化   它们出现在深度优先的从左到右的遍历中   基类的非循环图,其中“从左到右”是基数的顺序   派生类中基类的外观   基本符列表。

     

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

     

- 然后,非静态   数据成员按照在其中声明的顺序进行初始化   类定义(再次无论顺序如何   MEM-初始化)。

     

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

     

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

因此,您可以在基类中指定构造函数(它可以受到保护)并在派生类(should be preferred)的初始化列表中使用该构造函数,或者您可以分配给基础派生类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;
}