47

我很难在谷歌上找到这个。

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) {}
};

在铿锵声3.2:

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

1 回答 1

63

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

C++ 标准 n3337 § 12.6.2/10

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

— 首先,并且仅对于最派生类 (1.8) 的构造函数,虚拟基类按照它们在基类的有向无环图的深度优先从左到右遍历中出现的顺序进行初始化,其中“左-to-right”是派生类基类说明符列表中基类的出现顺序。

然后,直接基类按照它们出现在 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;
}
于 2013-08-28T04:22:30.067 回答