今天在弄一段代码的时候遇到了静态成员变量的问题。卡了一段时间后,果断翻出《深入探索C++对象模型》,大概明白了问题所在。这事给我的一点启示就是“纸上得来终觉浅,绝知此事要躬行”。首先看看问题吧!其实就是一个类型的定义。代码如下:
//myApplication.cpp #include "myapplication.h" #include <iostream> using std::cout; using std::endl; myApplication::myApplication(string _appName):appName(_appName) { if(self!=0) return; else self=this; } void myApplication::printAppname() { cout<<appName<<endl; } myApplication* myApplication::self=0;
//myApplication.h #ifndef MYAPPLICATION_H_INCLUDED #define MYAPPLICATION_H_INCLUDED #include <string> using std::string; #define myApp myApplication::instance() class myApplication { public: myApplication(string _appname); static myApplication* instance() {return self;} void printAppname(); private: static myApplication *self; string appName; }; #endif // MYAPPLICATION_H_INCLUDED
看到了myApplication* myApplication::self=0;这一行我就有点犯糊涂了。为什么要这样赋值呢?可不可以在类里面赋值呢?我试了试,答案是不可以的。查了一下C++规定了类的静态成员变量要在类外赋值。我有了疑问,为什么要这样规定呢?
查阅《深入探索C++面向对象模型》,我找到原因。首先类的静态成员变量是被所有类成员共享的,在内存中应该只有一份拷贝。为了实现这种特性,C++把静态成员变量用全局变量来进行了实现,只是这个全局变量的可见范围在这个类里边。所以,与其说在类定义中定义了静态变量,不如说是引用了静态变量。而类外的初始化赋值其实包含了定义。我试了一下,去掉这个所谓的类外赋值,编译器就会报“undefined references to ...”错误。
其次我还犯了另一个糊涂,静态变量是什么时候赋值的?我测试了一下,静态变量的赋值是在该类型的第一个对象被定义之前就已经完成了。到底是什么时候呢?其实转念一想,赋值语句其实并不一定要在运行时调用执行才能完成。编译、链接或者加载的时候就可以将这个“全局变量”初始化了”,应用程序运行之前,数据段的这个“全局变量”已经都被赋值好了。当然也有可能是通过.init段实现的。具体的情况以后再去深究了。
发表评论