【问题标题】:Initializing const member within class declaration in C++在 C++ 中的类声明中初始化 const 成员
【发布时间】:2012-02-26 20:32:33
【问题描述】:

在 PHP 和 C# 中,常量可以在声明时初始化:

class Calendar3
{
    const int value1 = 12;
    const double value2 = 0.001;
}

我有一个函子的以下 C++ 声明,它与另一个类一起用于比较两个数学向量:

struct equal_vec
{
    bool operator() (const Vector3D& a, const Vector3D& b) const
    {
        Vector3D dist = b - a;
        return ( dist.length2() <= tolerance );
    }

    static const float tolerance = 0.001;
};

这段代码用 g++ 编译没有问题。现在在 C++0x 模式 (-std=c++0x) 下,g++ 编译器会输出错误消息:

错误:类内初始化非整数类型的静态数据成员“tolerance”需要“constexpr”

我知道我可以在类定义之外定义和初始化这个static const 成员。此外,可以在构造函数的初始化列表中初始化非静态常量数据成员。

但是有什么方法可以在类声明中初始化一个常量,就像在 PHP 或 C# 中一样?

更新

我使用 static 关键字只是因为可以在 g++ 的类声明中初始化这些常量。我只需要一种方法来初始化类声明中的常量,无论它是否声明为static

【问题讨论】:

  • I used static keyword just because it was possible to initialize such constants within the class declaration in g++. I just need a way to initialize a constant in a class declaration no matter if it declared as static or not. 这是决定成员是否应为static错误方式。永远不要让词汇惰性决定代码的语义。
  • That's the wrong way to decide whether a member should be static or not. 我不同意。我认为这对于固定成员来说并不重要。
  • @expresso:一点也不。您可以使用特定于实例的信息初始化非static 常量成员。你已经决定你的常量是类型的属性而不是特定实例的属性是使它成为static 的原因,而不是因为你喜欢打字快捷方式。
  • @lightless:嗯,这是可能的,但我看不出有任何理由使用具有不同值的相同实例特定常量的初始化。我曾经为此使用非常量类字段!
  • 为什么,如果它们在对象实例化后从未改变? struct myType { const std::time_t instantiated; myType() : instantiated(std::time(0)) {} };所有可以const应该const;这适用于static 和非static 成员。

标签: c++ g++


【解决方案1】:

在 C++11 中,可以在类声明中初始化非static 数据成员、static constexpr 数据成员和static const 整数或枚举类型的数据成员。例如

struct X {
    int i=5;
    const float f=3.12f;
    static const int j=42;
    static constexpr float g=9.5f;
};

在这种情况下,类X 的所有实例的i 成员被编译器生成的构造函数初始化为5f 成员被初始化为3.12static const 数据成员j 被初始化为42static constexpr 数据成员g 被初始化为9.5

由于floatdouble 不是整数或枚举类型,因此此类成员必须是constexpr 或非static,才能允许类定义中的初始化程序。

在 C++11 之前,只有 static const 整数或枚举类型的数据成员可以在类定义中具有初始值设定项。

【讨论】:

  • 是否有指向标准部分的链接?我刚刚开始使用它(尽管编译为 C++14)并且很高兴它可以工作,因为我可以通过让编译器为我做这些来节省大量时间。但是,在阅读您的答案之前,我不确定它是否应该起作用!一个官方的话会帮助我建立信心,哈哈。 Fwiw 我也和char const n[3]{'a', 'b', 'c'}; 这样的成员一起工作。
  • 我想知道为什么static const intstatic constexpr floatfloat and double are not of integral or enumeration type 是什么意思?
  • @mrgloom :是的,float 和 double 不是。如果数据类型可以转换为整数,那么它就是整数类型。
  • 这个限制有什么意义?无论如何,谢谢你的好回答
【解决方案2】:

初始化 const int 类型以外的静态成员变量不是 C++11 之前的标准 C++。除非您指定 -pedantic 选项,否则 gcc 编译器不会就此发出警告(并生成有用的代码)。然后,您应该会收到类似于以下内容的错误:

const.cpp:3:36: error: floating-point literal cannot appear in a constant-expression
const.cpp:3:36: warning: ISO C++ forbids initialization of member constant ‘tolerance’ of non-integral type ‘const float’ [-pedantic]

这样做的原因是 C++ 标准没有指定应该如何实现浮点,而是留给了处理器。为了解决这个问题和其他限制,引入了constexpr

【讨论】:

  • 感谢“留给处理器”的提示。这让我从“WTF 是关于 uint32_t 和 float 之间初始化的技术差异?!?!?”开始思考。 “啊,好吧!” :-D
【解决方案3】:

是的。只需按照错误提示添加 constexpr 关键字即可。

【讨论】:

  • 也许他不想在他的项目中使用 C++11?
  • 他提到的问题是因为他试图编译为C++11,即他想支持C++11:)
【解决方案4】:

我遇到了真正的问题,因为我需要相同的代码来编译不同版本的 g++(GNU C++ 编译器)。所以我不得不使用宏来查看正在使用哪个版本的编译器,然后采取相应的行动,就像这样

#if __GNUC__ > 5
 #define GNU_CONST_STATIC_FLOAT_DECLARATION constexpr
#else
 #define GNU_CONST_STATIC_FLOAT_DECLARATION const
#endif

GNU_CONST_STATIC_FLOAT_DECLARATION static double yugeNum=5.0;

这将对 g++ 版本 6.0.0 之前的所有内容使用“const”,然后对 g++ 版本 6.0.0 及更高版本使用“constexpr”。这是对发生更改的版本的猜测,因为坦率地说,我直到 g++ 版本 6.2.1 才注意到这一点。要做到这一点,您可能需要查看 g++ 的次要版本和补丁号,请参阅

https://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html

有关可用宏的详细信息。

使用 gnu,您还可以坚持在任何地方都使用 'const',然后使用 -fpermissive 标志进行编译,但这会发出警告,我希望我的东西能够干净地编译。

不是很好,因为它是特定于 gnu 编译器的,但我怀疑你可以用其他编译器做类似的事情。

【讨论】:

    【解决方案5】:

    如果你只需要一种方法,你可以在本地声明它是静态的:

    struct equal_vec
    {
        bool operator() (const Vector3D& a, const Vector3D& b) const
        {
            static const float tolerance = 0.001f;
            Vector3D dist = b - a;
            return ( dist.length2() <= tolerance );
        }
    };
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-02-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-24
      • 2011-04-01
      • 1970-01-01
      相关资源
      最近更新 更多