我有一个类,它基本上只包含一堆通过我的应用程序使用的常量定义。但出于某种原因,long
编译但float
s不:
class MY_CONSTS
{
public :
static const long LONG_CONST = 1; // Compiles
static const float FLOAT_CONST = 0.001f; // C2864
};
给出以下错误:
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
我错过了什么吗?
答案 0 :(得分:56)
回答你问的实际问题:“因为标准是这么说的。”
只能在类声明中初始化静态,常量,整数类型(包括枚举)的变量。如果编译器支持浮点数的内联初始化,则它是扩展名。正如其他人所指出的,处理静态,常量,非整数变量的方法是在类的相应源文件(而不是标题)中定义和初始化它们。
C ++标准第9.2节“班级成员”第4项:
member-declarator 可以包含一个 常量初始化程序仅当它声明了静态成员(9.4)时 const integral或const枚举 类型,见9.4.2。
第9.4.2节“静态数据成员”第2项:
如果静态数据成员是const 整数或常数枚举类型, 它在班级定义中的声明 可以指定常量初始化程序 这应该是一个整数常数 表达式(5.19)。在那种情况下, 成员可以出现在整数常量中 表达式。该成员仍然是 如果是,则在命名空间范围内定义 用于程序和命名空间 范围定义不得包含 初始化
答案 1 :(得分:36)
您应该在其中一个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;
答案 2 :(得分:19)
见Stroustrup's explanation。相关报价:
通常在一个类中声明一个类 头文件和头文件是 通常包含在许多中 翻译单位。但是,要避免 复杂的链接器规则,C ++需要 每个对象都有一个独特的 定义。这条规则将被打破 如果C ++允许在类中定义 需要存储的实体 记忆作为对象。见D& E表示 解释C ++的设计权衡。
答案 3 :(得分:8)
其他人给出的标准措辞的基本原理是相同的,哪个模板参数不能是浮点数。为了获得一致的结果,您需要编译器实现与在编译时完成的相同的评估,并且对于交叉编译器以及在程序使用舍入模式进行的情况下,这可能很复杂。
从内存开始,在C ++ 0X中,常量表达式的概念已经扩展,因此您的代码将是有效的(但是在运行时或者在运行时计算时浮点常量表达式的结果是未指定的在编译时)。
答案 4 :(得分:3)
怎么样:
class MY_CONSTS
{
public :
static const long LONG_CONST;
static const float FLOAT_CONST;
};
const long MY_CONSTS::LONG_CONST = 1;
const float MY_CONSTS::FLOAT_CONST = 0.001f;
(但是,我不能对这个具体案例作出任何解释......)
答案 5 :(得分:3)
从标准9.4.2 / 4
如果静态数据成员是const 整数或常数枚举类型, 它在课堂上的宣言 定义可以指定一个 恒定初始化器应该是一个 积分常数表达式(5.19)。 在这种情况下,该成员可以出现在 积分常数表达式。该 会员仍应在a。中定义 命名空间作用域,如果它在 程序和命名空间范围 定义不得包含 初始化程序。
和5.19 / 1:
在一些地方,C ++需要 评估为的表达式 积分或枚举常数:as 数组边界(8.3.4,5.3.4),视情况而定 表达式(6.4.2),作为位字段 长度(9.6),作为调查员 初始化器(7.2),作为静态成员 初始化器(9.4.2),并作为整体 或枚举非类型模板 论证(14.3)。常量表达式: 条件表达式一个整数 常量表达只能涉及 文字(2.13),枚举数,常量 变量或静态数据成员 积分或枚举类型 用常量表达式初始化 (8.5),非类型模板参数 积分或枚举类型,和 sizeof表达式。 <强>浮动 文字(2.13.3)只有在出现时才会出现 他们被铸成积分或 枚举类型。只输入 转换为积分或枚举 类型可以使用。特别是, 除了sizeof表达式, 函数,类对象,指针或 引用不得