为什么不允许使用静态const浮点数?

Jon*_*age 64 c++ visual-c++

我有一个类,它基本上只包含我的应用程序使用的一堆常量定义.但出于某种原因,longs编译但float不是:

class MY_CONSTS
{
public :
    static const long   LONG_CONST = 1;      // Compiles 
    static const float FLOAT_CONST = 0.001f; // C2864
};
Run Code Online (Sandbox Code Playgroud)

给出以下错误:

1>c:\projects\myproject\Constant_definitions.h(71) : error C2864: 'MY_CONSTS::FLOAT_CONST' : only static const integral data members can be initialized within a class
Run Code Online (Sandbox Code Playgroud)

我错过了什么吗?

Tyl*_*nry 59

要回答你问的实际问题:"因为标准是这么说的".

只有静态,常量,整数类型(包括枚举)的变量可以在类声明中初始化.如果编译器支持浮点数的内联初始化,则它是扩展名.正如其他人所指出的,处理静态,常量,非整数变量的方法是在类的相应源文件(而不是标题)中定义和初始化它们.

C++标准第9.2节"类成员"第4项:

构件声明符可以包含一个 恒定的初始化仅当它声明const的积分或const枚举类型的静态成员(9.4),见9.4.2.

第9.4.2节"静态数据成员"第2项:

如果静态数据成员是const integer或const枚举类型,则它在类定义中的声明可以指定一个常量初始化器 ,它应该是一个整型常量表达式(5.19).在这种情况下,成员可以出现在整数常量表达式中.如果在程序中使用该成员,并且命名空间作用域定义不包含初始化程序,则该成员仍应在命名空间作用域中定义 .

  • 确实.很好,C++ 0x将支持类内的浮动初始化器. (10认同)
  • 另一个好方法是使函数返回该值.好处是编译器可以看到该值(可以内联函数).in-.cpp定义不会将值暴露给其他TU. (3认同)
  • 在 c++0x 中,您可以将返回类型声明为 `constexpr float` [http://en.wikipedia.org/wiki/C%2B%2B0x#Generalized_constant_expressions] (2认同)

Wil*_*ill 38

您应该在其中一个cpp文件的主体中初始化它们:

class MY_CONSTS
{
public :
    static const long   LONG_CONST = 1;      // Compiles 
    static const float FLOAT_CONST;
};

const float MY_CONSTS::FLOAT_CONST = 0.001f;
Run Code Online (Sandbox Code Playgroud)

  • 有些编译器仍然希望你在cpp文件中有另一行为`LONG_CONST`定义空间:`const long MY_CONSTS :: LONG_CONST;`注意你不要在这里重复初始化. (3认同)
  • @Adrian:区别在于这些编译器坏了. (3认同)

JRL*_*JRL 19

请参阅Stroustrup的解释.相关报价:

类通常在头文件中声明,并且头文件通常包含在许多翻译单元中.但是,为避免复杂的链接器规则,C++要求每个对象都有唯一的定义.如果C++允许将需要作为对象存储在内存中的实体的类内定义,则该规则将被破坏.有关C++设计权衡的解释,请参阅D&E.

  • long常量可以成为CPU指令的一部分(至少在Intel CPU上).浮动无助于记忆.使用略微滥用的符号,你可以说long可以内联,而浮点数不能. (15认同)
  • 这并没有真正回答这个问题.为什么`long`被初始化而``float`不能?可以假定`long`不需要'作为[对象]存储在内存中,但是`float`可以吗?这有什么意义? (12认同)

APr*_*mer 8

其他人给出的标准措辞的基本原理是相同的,其中模板参数不能是浮点数.为了获得一致的结果,您需要编译器实现与在编译时完成的相同的评估,并且对于交叉编译器以及在程序使用舍入模式进行的情况下,这可能很复杂.

从存储器,在C++ 0X,常量表达式的概念进行了扩展和因此您的代码将是有效的(但它是在浮点的结果未指定时,在运行时或在编译时评估常量表达式是相同的).


小智 7

在 C++11 及更高版本中,您可以使用 constexpr 定义类浮点常量:

class MY_CONSTS
{
public:
    static constexpr long  LONG_CONST = 1;      
    static constexpr float FLOAT_CONST = 0.001f;
};
Run Code Online (Sandbox Code Playgroud)