将类的静态成员定义放入cpp文件中——技术限制?

4

在编写C++代码时,我最讨厌的问题之一是在类中声明某些静态变量,然后看到编译错误,指出未解决的静态变量(在早期,我总是感到害怕,不知道这是什么意思)。

我的意思是经典的例子,如下:

Test.h

class Test
{
private:
  static int m_staticVar;
  int m_var;
}

Test.cpp

int Test::m_staticVar;

在我看来,更加令人困惑的是这个定义的语法。你不能在这里使用“static”关键字(因为在cpp中使用时有不同的含义),所以除了知道静态成员变量是这样工作的之外,你不知道为什么Test类中的某个int要以这种方式定义,而m_var却不用。
在您的认知/意见中,为什么会这样?我只能想到一个原因,那就是为了让链接器更容易处理-即出于与不能使用非整数常量(SomeClass m_var = something)相同的原因。但我不喜欢弯曲语言特性,只是因为编译链的某个部分难以理解它...

3
你的问题不是很清楚。 - anon
你使用的编译器是什么?我一直认为,除非你想将静态变量初始化为特定值,否则没有必要在类声明之外列出它。VS2008不会抱怨你的类定义,但那只是一个编译器,不能证明我是对的... - Praetorian
我同意,这样做很烦人。我认为cpp中的定义并不特别令人困惑,一旦你知道如何让链接器满意地处理静态成员,就不会有问题了。 - UncleBens
@Praetorian:其他编译器可能也是一样的。如果一个符号没有被使用,链接器就不需要它。 - UncleBens
1
@Praetorian:如果它是一个静态的const整数成员,在类声明中初始化,并且您从未执行需要获取其地址的操作,则不需要单独定义-它被视为编译时常量。否则,它是一个对象,每个对象必须在一个源文件中定义一次。 - Mike Seymour
显示剩余2条评论
2个回答

6

好的,这就是它的工作方式。您只在.h文件中声明了静态成员。链接器需要能够在链接在一起的对象文件中找到该静态成员的确切一个定义。您不能将定义放在.h文件中,否则会生成多个定义。

更新:C++17可以通过inline variable解决此问题。


从技术上讲,只要该文件未被包含在多个编译单元中,您可以将其放入.h文件中。 :) - grddev
1
另一方面,拥有模板(或内联函数)的多个定义,并让链接器选择一个是可以的... - UncleBens
2
@UncleBens:C++从来都不是一致的,这也是它迷人之处的一部分。 - Mike Seymour

1

首先,从编译器的角度来看,这是完全合理的。为什么在不需要的地方使用冗余关键字呢?

其次,我建议避免在 C++ 中使用静态成员。在所有人都跳出来批评之前,我将尝试解释。

嗯,你不会有任何公共静态数据成员(很少有用)。无论如何,大多数类都有自己的 CPP 文件。如果是这样,对于依赖性减少的原因,我认为静态全局优于私有静态成员。与非静态私有数据不同,静态数据不属于接口的一部分,用户不应该重新编译或查看这些成员。


你可能想要使用s/static global/variable in the anonymous namespace/。这样做会在模板中避免出现问题(它们具有唯一的外部链接;静态全局变量没有外部链接)。 - MSalters

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接