When A Class Member Encounters 'static'
在C++中,当一个类的成员遇到static限定符会是什么样子呢?今天在更新类CSymbolTable的过程中遭遇到这样的困境。
由于之前遇到过定义static的成员函数的问题,对于static成员函数来说并没有什么需要特别注意的,仅仅是该函数不能引用类的非static成员、没有this指针、在函数还引用只能加类作用符而非对象名。所以这次对于static的成员变量很有信心的在头文件中定义了。既然都是static的,那么在static的函数中引用static变量应该没有问题吧。写好函数,开始编译——奇怪的错误发生了:在编译的最后阶段——Linking的过程中,Visual Studio报告无法定位刚才定义的那个static成员变量的引用。按经验来说,这种错误发生的情况用extern声明的变量不能从其他文件.c/cpp中找到其定义;但是这个地方明明在头文件中已经清清楚楚地定义了呀。
不解之下只能求助MSDN。在static member的索引中找到一个例子,倒是可以成功编译的。二者不同的地方是MSDN的例子中居然在class定义的外部又对其static成员变量作了一次定义。还是不解,抱着试一试的心情翻开了电子版的C++ Primer,方便的索引功能帮我找到了问题的根源——(引自C++ Primer)static data members must be defined (exactly once) outside the class body. Unlike ordinary data members, static members are not initialized through the class constructor(s) and instead should be initialized when they are defined.
原来,static成员变量不是在类的构造函数中初始化的(这点很好理解,因为构造函数是在构造一个对象时调用的,static成员隶属于类而非任何该类的实例(对象);而我曾一度希望找到能定义static构造函数的方法,结果证实这在C++中是不存在的)。C++对于类声明中的static变量仅仅也就是作声明处理(其实非static的也一样,只不过后者在构造函数中分配内存空间和初始化的)。既然static是对整个类而言,那么只存在一个static变量的实例;而头文件中的声明是不分配内存空间的,那么需要在类声明的外部显式地进行定义/初始化就不难理解了。最后,为了保证该static成员只被定义一次,其定义语句应该放在类的.cpp文件中而不是.h文件中——(引自C++ Primer)The best way to ensure that the object is defined exactly once is to put the definition of static data members in the same file that contains the definitions of the class noninline member functions.
总结一下就是C++对static的实现和C#、Java有很大的区别。不能不说以前使用C#的static的经验误导了我。由于C++对类的声明和定义是分离的,分别放在.h和.cpp文件中,而.h中定义的static成员变量并不会在构造函数中初始化,所以,显式地在外部定义是必要的。
Labels: Pallyc Project

0 Comments:
Post a Comment
<< Home