前几天在逛论坛的时候看到一篇别人问的帖子,说的是静态成员变量的初始化顺序问题。
当时没有细看,后来仔细想想也没有想得很明白,大致回忆了一下,先贴出来给大家看看……
1 #include <iostream>
2
3 using namespace std;
4
5 class ClassA {
6 public:
7 ClassA():m_nNum(5) {
8 cout << "Member Val:" << m_nNum << endl;
9 cout << "ClassA Constructor!" << endl;
10 }
11 void Func() {
12 cout << "Member Val:" << m_nNum << endl;
13 cout << "ClassA Func() Called!" << endl;
14 }
15 int m_nNum;
16 };
17
18 class ClassB {
19 public:
20 ClassB() {
21 cout << "Class B Constructor! " << endl;
22 s_A.Func();
23 }
24
25 protected:
26 static ClassA s_A;
27 };
28
29 ClassB TestClass;
30 ClassA ClassB::s_A;
31
32
33 int main(int argc, char *argv[])
34 {
35 system( "PAUSE ");
36 return 0;
37 }
38
这段代码就是讲的在ClassB中有一个静态成员变量ClassA s_A,ClassB在构造时会调用ClassB::s_A的Func()方法.
但是后面在初始化ClassB::s_A时,却把初始化的位置写在了一个ClassB的实例之后.
并且程序能够正常的通过编译并运行。输出结果如下:
Class B Constructor!
Member Val:0
ClassA Func() Called!
Member Val:5
ClassA Constructor!
让我不理解的是,在没有初始化静态成员变量之前,ClassB是如何能正常调用ClassB::s_A的Func()方法呢?
最后个人得出的答案是:
在程序编译"ClassA ClassB::m_cA;" 时就已经对ClassB::s_A分配了空间
(以至于ClassB::s_A.Func()在读取成员变量m_nNum时能正确的找到位置不至于报错)
但是因为不是内置类型,所以只有等到运行时再来调用构造函数来进行初始化.
实际上,在全局对象TestClass定义时调用ClassB::s_A.Func()和跟下面代码类似:
1 class ClassA {
2 public:
3 void Func() {
4 cout << "ClassA Func() Called!" << endl;
5 }
6 };
7
8 int main(int argc, char *argv[])
9 {
10 ClassA * pFunc = NULL;
11 pFunc->Func();
12
13 system( "PAUSE ");
14 return 0;
15 }
16
这里因为没有涉及成员变量的访问,所以不会因为访问错误的内存地址而报错. 之前的例子因为编译时已为ClassB::s_A分配了空间,这使在没有初始化ClassB::s_A之前访问Func()方法不会有问题,因为能够正确找到成员变量的地址.
以上就是个人得出的已经结论,不过回头还得再看看<
Inside The C++ Object Model>中能否找到具体的依据。在此也希望各位牛人对此有任何看法能指点一二!