我有一个类,它基本上只包含我的应用程序使用的一堆常量定义.但出于某种原因,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).在这种情况下,成员可以出现在整数常量表达式中.如果在程序中使用该成员,并且命名空间作用域定义不包含初始化程序,则该成员仍应在命名空间作用域中定义 .
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)
JRL*_*JRL 19
请参阅Stroustrup的解释.相关报价:
类通常在头文件中声明,并且头文件通常包含在许多翻译单元中.但是,为避免复杂的链接器规则,C++要求每个对象都有唯一的定义.如果C++允许将需要作为对象存储在内存中的实体的类内定义,则该规则将被破坏.有关C++设计权衡的解释,请参阅D&E.
其他人给出的标准措辞的基本原理是相同的,其中模板参数不能是浮点数.为了获得一致的结果,您需要编译器实现与在编译时完成的相同的评估,并且对于交叉编译器以及在程序使用舍入模式进行的情况下,这可能很复杂.
从存储器,在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)