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

我有一个类,它实际上只是包含了一些通过我的应用程序使用的常量定义。但出于某种原因,long编译而 float不编译:

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

我错过了什么吗?

52439 次浏览

应该在 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;

那么:

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;

(虽然,我不能给出任何解释这个具体的情况...)

Stroustrup 的解释相关引文:

类通常在 头文件和头文件是 通常包括在许多 翻译单位。然而,为了避免 复杂的链接器规则,C + + 需要 每个物体都有其独特之处 定义,这条规则就会被打破 如果 C + + 允许在类中定义 需要存储在 记忆作为对象。参见 D & E 解释 C + + 的设计权衡。

回答你提出的实际问题: “因为标准是这么说的”。

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

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

成员声明程序成员声明程序可以包含 Constant-initializer 仅当它声明了 常数整数或常数枚举 类型,见9.4.2。

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

如果静态数据成员为 const,则为 整数或常数枚举类型, 它在类定义中的声明 可以指定 常量初始化器常量初始化器 它应该是一个整数常数 表达式(5.19)。在这种情况下, 元件可以以积分常数形式出现 表达式。该成员仍然是 如果是在命名空间范围中定义的,则为 在程序和命名空间中使用 范围定义不得包含 初始化程序。

从标准的9.4.2/4

如果静态数据成员为 const,则为 整数或常数枚举类型, 它在类中的声明 定义可以指定一个 常量初始值设定项,它应该是 积分常数表达式(5.19)。 在这种情况下,该成员可以出现在 积分常数表达式 成员仍须在 命名空间范围中使用 程序和命名空间范围 定义不得包含 初始化程序。

5.19/1:

在一些地方,C + + 需要 计算结果为 整数或枚举常数 数组边界(8.3.4,5.3.4) ,视情况而定 表达式(6.4.2) ,作为位字段 长度(9.6) ,作为枚举数 初始化器(7.2) ,作为静态成员 初始化程序(9.4.2) ,并作为整数 或枚举非类型模板 参数(14.3)常量表达式: 条件表达式积分 常量表达式只能涉及 字面值(2.13) ,枚举数,常量 变量或静态数据成员 整数或枚举类型 用常量表达式初始化 (8.5)的非类型模板参数 整数或枚举类型,以及 表达式的大小。 浮动 文字(2.13.3)只有在下列情况下才能出现: 它们被铸成积分或 枚举类型 . Only 类型 转换为整数或枚举 类型。特别是, 除了表达式的大小, 函数、类对象、指针或 参考文献不得

其他人给出的标准措辞下的基本原理是相同的,即模板参数不能是浮点数。为了得到一致的结果,你需要编译器实现与编译时相同的计算,这对于交叉编译器和程序使用舍入模式的情况是很复杂的。

在内存中,在 C + + 0X 中,常量表达式的概念已经被扩展,因此你的代码将是有效的(但是在浮点常量表达式在运行时或编译时计算的结果是相同的,这是未指定的)。

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

class MY_CONSTS
{
public:
static constexpr long  LONG_CONST = 1;
static constexpr float FLOAT_CONST = 0.001f;
};