【问题标题】:Invalid use of non-static data memeber [duplicate]非静态数据成员的无效使用[重复]
【发布时间】:2013-08-22 16:32:21
【问题描述】:

我在 A.h 中有以下代码:

class A
{
public:
    ...
private:
    ...
    const int X = 1;
    float Y[X];
    ...
};

如果项目中仅包含头文件 A.h,则编译良好。但是,如果我在 A.cpp 中包含 A.h,它会给我如下奇怪的错误:

... 警告:非静态数据成员初始化器仅适用于 -std=c++11 或 -std=gnu++11 [默认启用]

...错误:非静态数据成员'A::X'的使用无效

...错误:来自这个位置

即使我更改const int X = 1;(尽管我需要它作为常量参数),也没有任何变化。

附言如果有意义的话,我正在使用 Qt 5.1

附言实际上使它 static 修复了错误。但是为什么我必须这样做呢?

【问题讨论】:

  • 很抱歉,我不认为这个问题是重复的。请阅读我的问题更多。
  • 不想回答您的问题,但这正是您要问的。为了简单地回答这个问题,您可以将X 设为静态,或者您不能做您想做的事情。
  • 我意识到这一点。我的问题是“为什么?”。我想了解为什么我需要这样做,而不仅仅是复制粘贴。
  • 如果你想要一个常量数据成员并且成员的值对于类的每个实例总是相同的,那么拥有该成员的多个副本是没有意义的。最好为所有实例使用一个静态成员。
  • 当你设法让它工作时,你是如何编译它的?你确定头文件被解析了吗?

标签: c++ qt constants static


【解决方案1】:

第一个问题是您正在针对旧版本的 C++ 进行编译,它不允许在声明中初始化非静态(即每个对象而不是每个类)成员。您可以针对 C++11 进行编译(如错误消息所示);或者在构造函数中初始化它;或者设为static,如果您不需要为您创建的每个对象设置单独的值。

第二个问题是数组大小必须是编译时常量。非静态成员 const 或其他成员不符合要求。原则上,它可以在不同的对象中具有不同的值(即使它在声明中这样初始化,它也可以被一个或多个构造函数覆盖),因此没有编译时值。静态成员确实有一个固定的值,所以如果值可用,可以用作数组大小。

【讨论】:

    【解决方案2】:

    您的意图是在类中有一个constant 变量。

    现在这个类用于创建许多对象。实际上,该类应该允许每个对象对于 const 数据成员具有不同的 const 值,因此您不能在类内初始化 const 成员。

    const 内部类成员意味着该值在对象的整个生命周期内都是恒定的。

    这就是为什么存在一个称为constructor initialization list 的特殊初始化点,而不是允许在构造函数中进行初始化。

    现在,如果您被允许在构造函数内初始化 const 成员,那么您可以在构造函数本身内多次重新分配它,这会破坏 const 的含义(这意味着,分配一次并且保持不变整个)。

    因此const 成员的初始化应该发生在构造函数之前,这是在初始化列表中完成的。如果您愿意,这会为您提供const 成员对不同对象的不同值。

    另外,注意构造函数i(ii)中初始化的形式是在进入构造函数之前初始化数据成员

    class A
    {
        const int i;
        public:
           A(int ii): i(ii)
           {
              // i  = 5; Can't do this since i is `const`
           }
    };
    

    话虽如此,如果您希望所有对象共享相同的 const 值,那么您可以使用其他答案中指出的 static const 限定符。

    正如 Mike Seymour 指出的那样,对于数组分配或初始化 const 变量,您需要具有编译时常量,但类内部的 consts 不会给您编译时间常量,因此您必须使用static const 限定符使其成为编译时间常数。

    【讨论】:

      【解决方案3】:

      您想在A 的构造函数初始化列表中初始化X,因为它是Anon-static const 成员:

      class A {
          const int X;
      public:
          A() : X(1) {
              // ...
          }
          // ...
      

      也就是说,从类A 实例化的每个对象都有一个名为Xint 成员(即non-static 部分,即它不是该类的成员),即const(它可以'不能被修改或重置,所以你必须在构造函数初始化列表中初始化它,而不是在构造函数体中)。

      【讨论】:

      • 您能否重新表述您的答案?不清楚。谢谢。
      • 重新表述了答案,是不是更清楚了?
      • 现在好多了,谢谢
      【解决方案4】:

      很简单

      • static const int X = 1;
      • 枚举 { X = 1 }; // 可怜的人 constexpr

      【讨论】:

      • 感谢您的回答。正如您在帖子中所看到的 - “实际上将其设为静态修复了错误”,我知道静态修复了错误,但我真的不明白为什么在这种情况下我必须使用静态。关于“枚举 { X = 1 };” - 我为什么需要这个?
      • @Mike 你可以获得'static const int'的地址(因此程序中有一些内存),枚举值将没有(没有内存,只是一个值)。如果您有 C++ 11,请使用 constexpr
      • 感谢您的澄清。
      【解决方案5】:

      这是你的罪魁祸首

          float Y[X];
      

      由于您试图通过名称 Y 来声明一个大小为 X 的浮点数组。但它是类的非静态私有成员。

      因此,X 将在符号表中,但在编译上述行期间无法访问关联的值,因此会出现警告和错误。

      【讨论】:

      • X 不会出现在符号表中以帮助进行常量折叠。对于const 的成员,类存储总是被分配,因此常量折叠失败。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-01-22
      • 1970-01-01
      • 1970-01-01
      • 2016-01-12
      • 2023-03-12
      • 2013-10-14
      • 2015-06-26
      相关资源
      最近更新 更多