【问题标题】:member initializer does not name a non-static data member or base class [duplicate]成员初始值设定项未命名非静态数据成员或基类 [重复]
【发布时间】:2013-08-31 00:26:52
【问题描述】:

我很难在谷歌上找到这方面的点击率。

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

【问题讨论】:

  • 为什么?我还没有做出“邪恶传承钻石”。 @AndreyT 该问题中接受的答案说要制作一个基本的ctor。我有一个……哦。我想我需要调用基类ctor,而不是成员ctor。好的。
  • @WhozCraig:即使它是一个虚拟基地,它仍然不会让你初始化间接成员。虚拟继承可能需要初始化间接,而不是成员。
  • @Steven Lu:接受的答案是a::m_z 只能从a 的构造函数初始化列表中初始化。它不能在b 的构造函数初始化列表中提及(如您的代码中所示)。语言不允许这样做。这才是重点。 IE。您必须向a 的构造函数添加另一个参数,专门针对m_z(就像您为m_x 所做的那样)并通过该构造函数从b 传递初始值。顺便说一句,在您上面的代码中,您必须从b 的构造函数中引用a 的构造函数。否则,它将无法编译,因为您在 a 中没有默认构造函数。
  • 知道了,谢谢。关闭这个问题很好,但我认为它应该保持可搜索状态,以便出现此错误的用户可以快速找到解决方案。
  • @AndreyT 说得对,先生,我暂时被剥夺睡眠和同时送来的比萨饼分心。嗯。删除评论。

标签: c++ c++11 clang


【解决方案1】:

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

C++ 标准 n3337 § 12.6.2/10

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

——首先,并且仅适用于最 派生类(1.8),虚拟基类按顺序初始化 它们出现在定向的深度优先从左到右遍历 基类的无环图,其中“从左到右”是 派生类中基类的外观 基本说明符列表。

然后,直接基类被初始化 出现在基本说明符列表中的声明顺序 (不管 mem-initializers 的顺序如何)。

那么,非静态的 数据成员按照它们在 类定义(同样不管 内存初始化器)。

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

[注:声明顺序的任务是确保基础和 成员子对象以相反的顺序被销毁 初始化。 ——尾注]

所以你可以在基类中指定一个构造函数(它可以被保护)并在派生类的初始化列表中使用它(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;
}

【讨论】:

  • 您的代码示例是错误的:OP 是要执行 m_z = z,而不是 m_x = z,当然,A(z) 在这种情况下是错误的(这也意味着 m_z 不是在 A 对象中初始化,m_x 未在 B 对象中初始化)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-07-12
  • 2013-11-12
  • 1970-01-01
  • 2020-05-02
  • 1970-01-01
  • 1970-01-01
  • 2016-10-15
相关资源
最近更新 更多