C++ 为什么不允许静态常量浮点数?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2454019/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why aren't static const floats allowed?
提问by Jon Cage
I have a class which is essentially just holds a bunch of constant definitions used through my application. For some reason though, long
s compile but float
s do not:
我有一个类,它本质上只包含一堆通过我的应用程序使用的常量定义。出于某种原因,long
s 编译但float
s 不:
class MY_CONSTS
{
public :
static const long LONG_CONST = 1; // Compiles
static const float FLOAT_CONST = 0.001f; // C2864
};
Gives the following error:
给出以下错误:
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
Am I missing something?
我错过了什么吗?
采纳答案by Tyler McHenry
To answer the actual question you asked: "because the standard says so".
要回答您提出的实际问题:“因为标准是这样说的”。
Only variables of static, constant, integraltypes (including enumerations) may be initialized inside of a class declaration. If a compiler supports in-line initialization of floats, it is an extension. As others pointed out, the way to deal with static, constant, non-integral variables is to define and initialize them in the class's corresponding source file (not the header).
只有静态、常量、整型(包括枚举)的变量可以在类声明中初始化。如果编译器支持浮点数的内联初始化,则它是一个扩展。正如其他人指出的那样,处理静态、常量、非整数变量的方法是在类的相应源文件(而不是头文件)中定义和初始化它们。
C++ Standard Section 9.2 "Class Members" item 4:
C++ 标准第 9.2 节“类成员”第 4 项:
A member-declaratorcan contain a constant-initializeronly if it declares a static member (9.4) of const integral or const enumeration type, see 9.4.2.
甲构件声明符可以包含一个 恒定的初始化仅当它声明const的积分或const枚举类型的静态成员(9.4),见9.4.2。
Section 9.4.2 "Static Data Members" item 2:
第 9.4.2 节“静态数据成员”第 2 项:
If a static data member is of const integral or const enumeration type, its declaration in the class de?nition can specify a constant-initializerwhich shall be an integral constant expression (5.19). In that case, the member can appear in integral constant expressions. The member shall still be de?ned in a namespace scope if it is used in the program and the namespace scope de?nition shall not contain an initializer.
如果静态数据成员是 const 整型或 const 枚举类型,则它在类定义中的声明可以指定一个常量初始化器,它应该是一个整型常量表达式(5.19)。在这种情况下,成员可以出现在整数常量表达式中。如果在程序中使用该成员,则该成员仍应在名称空间范围内定义,并且名称空间范围定义不应包含 初始化程序。
回答by Will
You should initialize them in the body of one of your cpp files:
您应该在您的 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;
回答by JRL
See Stroustrup's explanation. Relevant quote:
参见Stroustrup 的解释。相关报价:
A class is typically declared in a header file and a header file is typically included into many translation units. However, to avoid complicated linker rules, C++ requires that every object has a unique definition. That rule would be broken if C++ allowed in-class definition of entities that needed to be stored in memory as objects. See D&E for an explanation of C++'s design tradeoffs.
类通常在头文件中声明,而头文件通常包含在许多翻译单元中。但是,为了避免复杂的链接器规则,C++ 要求每个对象都有唯一的定义。如果 C++ 允许需要作为对象存储在内存中的实体的类内定义,那么这条规则就会被打破。有关 C++ 设计权衡的解释,请参阅 D&E。
回答by AProgrammer
The rationale under the standard wording that others have given is the same for which template arguments can't be floating point number. To get consistent result you'll need the compiler implement the same evaluation as the one done at compile time, and that can be complicated for cross-compiler and in the case where the program plays with rounding mode.
其他人给出的标准措辞下的基本原理与模板参数不能是浮点数的基本原理相同。为了获得一致的结果,您需要编译器实现与在编译时完成的评估相同的评估,这对于交叉编译器和程序以舍入模式播放的情况可能会很复杂。
From memory, in C++0X, the notion of constant expression has been extended and so your code would be valid (but it is unspecified in the result of floating point constant expressions are the same when evaluated at run-time or at compile time).
从内存来看,在 C++0X 中,常量表达式的概念已被扩展,因此您的代码将是有效的(但未指定浮点常量表达式的结果在运行时或编译时计算时相同)。
回答by Adrien Plisson
what about:
关于什么:
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;
(though, i cannot give any explanation of this specific case...)
(虽然,我无法对这个特定案例做出任何解释......)
回答by Andreas Brinck
From standard 9.4.2/4
从标准 9.4.2/4
If a static data member is of const integral or const enumeration type, its declaration in the class definition can specify a constant-initializer which shall be an integral constant expression (5.19). In that case, the member can appear in integral constant expressions. The member shall still be defined in a namespace scope if it is used in the program and the namespace scope definition shall not contain an initializer.
如果静态数据成员是 const 整型或 const 枚举类型,则它在类定义中的声明可以指定一个常量初始化器,它应该是一个整型常量表达式 (5.19)。在这种情况下,成员可以出现在整数常量表达式中。如果在程序中使用该成员,则该成员仍应在名称空间范围内定义,并且名称空间范围定义不应包含初始化程序。
And 5.19/1:
和 5.19/1:
In several places, C + + requires expressions that evaluate to an integral or enumeration constant: as array bounds (8.3.4, 5.3.4), as case expressions (6.4.2), as bit-field lengths (9.6), as enumerator initializers (7.2), as static member initializers (9.4.2), and as integral or enumeration non-type template arguments (14.3). constant-expression: conditional-expression An integral constant-expression can involve only literals (2.13), enumerators, const variables or static data members of integral or enumeration types initialized with constant expressions (8.5), non-type template parameters of integral or enumeration types, and sizeof expressions. Floating literals (2.13.3) can appear only if they are cast to integral or enumeration types. Only type conversions to integral or enumeration types can be used. In particular, except in sizeof expressions, functions, class objects, pointers, or references shall not
在一些地方,C++ 需要计算为整数或枚举常量的表达式:作为数组边界 (8.3.4, 5.3.4),作为 case 表达式 (6.4.2),作为位域长度 (9.6),作为枚举器初始值设定项 (7.2),作为静态成员初始值设定项 (9.4.2),以及作为整数或枚举非类型模板参数 (14.3)。常量表达式:条件表达式 整型常量表达式只能涉及用常量表达式 (8.5) 初始化的整型或枚举类型的文字 (2.13)、枚举数、常量变量或静态数据成员、整型或枚举的非类型模板参数类型和大小表达式。浮动文字 (2.13.3) 仅在它们被强制转换为整数或枚举类型时才能出现. 只能使用到整数或枚举类型的类型转换。特别是,除了 sizeof 表达式之外,函数、类对象、指针或引用不应