用汇编的眼光看C++(之类静态变量、静态函数)13(转)
【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】
看过设计模式的朋友都知道,我们在设计单件模式的时候离不开类的静态函数。和类的成员变量不同,类的静态变量属于全部类对象数据;同样和类的成员函数不 同,类的静态函数属于全部类函数共有。这句话读来想来有一些拗口,不过没有关系,我们可以通过一段代码来说明问题。
(1)静态变量
老规矩,我们首先对类进行初步定义,如下所示:
- class employee
- {
- public:
- employee() { }
- ~employee() {}
- static int value;
- };
那么,这里出现的value是不是所共有的,我们可以看看相关的函数代码即可:
- 67: int employee::value = 0;
- 68:
- 69: void process()
- 70: {
- 00401240 push ebp
- 00401241 mov ebp,esp
- 00401243 push 0FFh
- 00401245 push offset __ehhandler$?process@@YAXXZ (0041f469)
- 0040124A mov eax,fs:[00000000]
- 00401250 push eax
- 00401251 mov dword ptr fs:[0],esp
- 00401258 sub esp,48h
- 0040125B push ebx
- 0040125C push esi
- 0040125D push edi
- 0040125E lea edi,[ebp-54h]
- 00401261 mov ecx,12h
- 00401266 mov eax,0CCCCCCCCh
- 0040126B rep stos dword ptr [edi]
- 71: employee m;
- 0040126D lea ecx,[ebp-10h]
- 00401270 call @ILT+35(employee::employee) (00401028)
- 00401275 mov dword ptr [ebp-4],0
- 72: employee n;
- 0040127C lea ecx,[ebp-14h]
- 0040127F call @ILT+35(employee::employee) (00401028)
- 73:
- 74: m.value = 10;
- 00401284 mov dword ptr [employee::value (00438494)],0Ah
- 75: n.value = 100;
- 0040128E mov dword ptr [employee::value (00438494)],64h
- 76: }
- 00401298 lea ecx,[ebp-14h]
- 0040129B call @ILT+0(employee::~employee) (00401005)
- 004012A0 mov dword ptr [ebp-4],0FFFFFFFFh
- 004012A7 lea ecx,[ebp-10h]
- 004012AA call @ILT+0(employee::~employee) (00401005)
- 004012AF mov ecx,dword ptr [ebp-0Ch]
- 004012B2 mov dword ptr fs:[0],ecx
- 004012B9 pop edi
- 004012BA pop esi
- 004012BB pop ebx
- 004012BC add esp,54h
- 004012BF cmp ebp,esp
- 004012C1 call __chkesp (004086b0)
- 004012C6 mov esp,ebp
- 004012C8 pop ebp
- 004012C9 ret
我们直接看74行和75行。我们看到复制的对象地址都是惊人的一致,这说明实际上m和n所指的value实际上是同一个地址0x401005。不过,类的静态对象有一个要求,那就是对象的静态变量必须像全局变量一样进行初始化操作。
(2)静态函数
静态函数和静态变量一样,实际上就是类的全局函数。它之所以和普通的成员函数不一样,就是因为它不需要定义类的类型就能使用这个函数。根据上面的信息,我们可以重新定义一下这个类:
- class employee
- {
- public:
- employee() { }
- ~employee() {}
- static void print() { printf("employee::print()!\n");};
- };
那么类的静态函数是这样使用的呢?大家看看下面这样一个函数:
- 68: void process()
- 69: {
- 00401230 push ebp
- 00401231 mov ebp,esp
- 00401233 sub esp,40h
- 00401236 push ebx
- 00401237 push esi
- 00401238 push edi
- 00401239 lea edi,[ebp-40h]
- 0040123C mov ecx,10h
- 00401241 mov eax,0CCCCCCCCh
- 00401246 rep stos dword ptr [edi]
- 70: employee::print();
- 00401248 call @ILT+0(employee::print) (00401005)
- 71: }
- 0040124D pop edi
- 0040124E pop esi
- 0040124F pop ebx
- 00401250 add esp,40h
- 00401253 cmp ebp,esp
- 00401255 call __chkesp (00408620)
- 0040125A mov esp,ebp
- 0040125C pop ebp
- 0040125D ret
静态函数不需要对应的类对象,所以也就不需要this指针。这就是成员函数和静态函数的区别,仅此而已。
【预告: 下面一篇博客介绍类的算术重载符】