我有这个问题困扰我。
为什么我的.hpp
文件中没有这样的代码。
class H {
private:
static const int i =5;
static const float f = 1.0;
static const string s = "string";
}
只能声明和初始化int,bool,enum和constexpr等。
我的问题:
为什么字符串和其他复杂数据类型需要在cpp中正确初始化?它们是不变的。
为什么我们对浮点数和整数有不同的行为?我的猜测:gcc不支持,但如果我们使用constexpr,可以很容易地支持。
答案 0 :(得分:1)
这是因为标准是这样说的。
通常,out-of-line定义规则适用于static const
成员:
在其类定义中声明
static
数据成员不定义。
唯一的例外是,因为C ++ 11 integral和enum static const
类型可以在线初始化。
见[class.static.data]/3(强调我的):
如果非易失性
const static
数据成员属于整数或枚举类型,则其在类定义中的声明可以指定大括号 - or-equal-initializer ,其中 assignment-expression 的每个 initializer-clause 都是一个常量表达式。
作为Bjarne mentioned:
为什么存在这些不方便的限制?类通常在头文件中声明,并且头文件通常包含在许多翻译单元中。但是,为避免复杂的链接器规则,C ++要求每个对象都有唯一的定义。如果C ++允许将需要作为对象存储在内存中的实体的类内定义,则该规则将被破坏。
理性可能是整数类型成为编译时常量,虽然我倾向于不同意,因为编译单元中单个地址的规则仍然适用,这意味着编译器仍然必须发出static const
成员弱链接并让链接器折叠它们,就像使用多重定义的模板一样。此时对整体类型的限制变得没有实际意义,因为相同的折叠可以应用于任何类型。事实上,C ++ 17"修复"它与inline
成员:
class H {
private:
inline static const int i = 5;
inline static const float f = 1.0;
inline static const string s = "string";
};