在类定义中初始化的静态整数数据成员可以声明为const
或constexpr
,但在类定义中初始化的非整数静态数据成员必须是constexpr
:
class MyClass {
static const int w = 5; // okay
static constexpr int x = 5; // okay
static const float y = 1.5; // error!
static constexpr float z = 1.5; // okay
};
有人知道为什么不允许y的声明吗?标准的非法部分是9.4.2 / 3,但为什么是非法的?
答案 0 :(得分:4)
在C ++ 11之前,您无法在类声明中初始化非整数/枚举类型的静态成员(但您可以在类声明之外)。管理constexpr
的规则会带来前进,但允许您在课程声明中使用constexpr
对其进行初始化(因此您不再需要以下代码):
struct A
{
static const float pi;
};
const float A::pi = 3.1415;
此规则的一个副作用是简化您的类结构而不是让它变得丑陋(如上面的代码)。
在C ++ 11添加constexpr
之前的情况之一的原因之一是标准没有指定如何实现浮点(它留给处理器/体系结构 - 例如,当您说float x = 1.6f
时,在大多数系统上它实际上是1.6000000000024
。
答案 1 :(得分:2)
float
有点难以描述动机,但想象一下班级成员:
class MySpecialInt {
public:
constexpr MySpecialInt(const int & other) {
}
};
class MyClass {
static const MySpecialInt a = 5; // error
static constexpr MySpecialInt b = 5; // okay
};
a
在这种情况下可能有一些非平凡的结构,可能违反(或至少非常复杂)单定义规则。由于constexpr
保证了限制性编译时属性,b
的复制构造函数必须也是constexpr
,因此保证返回定义良好的编译时的值(和 NOT 违反单一定义规则)
为什么float
表现出这种行为我认为只是出于遗留原因,因为float
传统上从未像这样初始化("因为标准是这样说的"),所以他们在static
的保护下抓住了初始化const
float
constexpr
个成员。
答案 2 :(得分:0)
可能是因为非整数i也可能包含像char这样的数据类型,这就是为什么你不能使它们保持不变并需要常量表达的原因。但是在积分的情况下,你可以使它们成为常量表达式或不变。因此,因为char只能是一个常量表达式,所以对于所有非整数值都是非法的。