C++ 为什么静态成员初始化需要是";再打一次;?

C++ 为什么静态成员初始化需要是";再打一次;?,c++,class,static,initialization,C++,Class,Static,Initialization,情况就是这样。静态类成员在使用该类之前必须初始化,因为静态成员不是对象可靠的。它们在堆中占据自己的存储位置。 但我对初始化必须遵循的规则感到困惑 下面的代码解释了我的担忧 class TEST { public: ... static int val; ... } //Initialization //int TEST::val = 1;//This is correct. TEST::val = 1; //This is wrong, compiler msg: lac

情况就是这样。静态类成员在使用该类之前必须初始化,因为静态成员不是对象可靠的。它们在堆中占据自己的存储位置。 但我对初始化必须遵循的规则感到困惑

下面的代码解释了我的担忧

class TEST
{
public:
    ...
    static int val;
    ...
}
//Initialization
//int TEST::val = 1;//This is correct.
TEST::val = 1; //This is wrong, compiler msg: lack of type identifier.
//I think that the val member has been declared as int type.
//So WHY must I redeclare its type again? Or I did just miss something?

static int val
是一个声明(只是一个类型和名称,没有内存,没有值)。定义“分配”存储(可能是没有默认构造函数的垃圾),初始化会另外分配一个值。它与函数原型和实际定义相同。理论上,没有什么能阻止C++设计器跳过“代码> Val< /Cuth>成员定义中的类型。事实上,编译器已经知道类型,并且看起来像赋值的语法在函数之外是无效的,因此没有什么可以阻止编译器实现这种方法

但是,这会使解析器更加复杂,因为同一构造(赋值)必须根据上下文进行不同的解释。换句话说,是同一行

TEST::val = 1;
意味着函数内外完全不同的东西。在函数内部使用时,该行将被视为赋值;当在函数外部使用时,同一行将被视为定义


为了让自己和语言用户的生活变得不那么复杂,设计师们决定使用熟悉的语法来定义,而只需让用户重复一下就可以了。

为什么需要在定义中给出函数的返回类型?可能
auto TEST::val=1可能是下一个标准的好建议?!如果存在相应的声明,定义可以推断类型。我只能猜测,原因是人们希望将静态成员定义的语法与符号定义的一般语法对齐(而不是仅仅赋值的语法)。如果符号定义具有不同的语法(取决于它们是否定义了预先声明的符号),则会造成混淆。(出于类似的原因,如果允许使用
auto
,我会感到困惑,因为
auto
通常意味着“从值派生类型”,而不是“从以前的声明派生类型”。)我认为OP的观点是编译器已经知道
TEST::val
是从其声明中派生的
int
,那么为什么它不利用这些知识让您跳过在第二个位置指定
int
。关于函数原型也可以问同样的问题(而且也没有特别好的答案)。@dasblinkenlight:我可能不会回答实际的问题。为了简单起见,这是设计所必需的。在一个简单的编辑器中,我不想仅仅为了找出实际的类型而在标题和翻译单元之间切换。这样,标题与翻译单元的耦合也就不那么紧密了。绝对-这就是为什么我说OP的问题没有特别好的答案。@dasblinkenlight:考虑到函数可以重载,它们有很大的不同。@MatthieuM。至于他们的回报类型,我认为这只是猜测;也许你的思路是对的,但我同样可以说这要归结到C是如何做到的:
extern int const a后接
int const a=5和C++只添加了类名。当然,除非你有消息来源。@MatthieuM。同样的逻辑可以应用于
extern
s,但代价是必须使
extern
声明在翻译单元中定义相应
extern
变量的点处可见(当前是可选的)。对于静态类成员,它是必需的。@MatthieuM。编译器的这种逻辑如何?val定义了吗?是-->分配;没有-->定义。@richard.g:问题不在于什么是可行的(更现代的语言有更好的语法),而在于什么是可行的以及它是如何产生的。是的,C和C++可以做得更好;但坦率地说,如果我必须改革语言,我会更少地关注语法,而更多地关注语义,不定义的行为是一个更大的罪恶。