用汇编的眼光看C++(之缺省模板、特化模板)
【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】
缺省函数是C++的一个基本特色。缺省函数定义比较简单,也就是说,对于函数的某一个输入参数或者几个输入参数,如果你没有特定的数值的话,那我们就会用缺省的数据进行代替。如果你在调用的过程中使用了自己的数据,那么缺省数据将被我们自己定义的数据覆盖。下面就是一个缺省函数的示例:
- int add(int m, int n = 10)
- {
- return m + n;
- }
- 262: int p = add(2);
- 00401488 push 0Ah
- 0040148A push 2
- 0040148C call @ILT+15(add) (00401014)
- 00401491 add esp,8
- 00401494 mov dword ptr [ebp-4],eax
- 263: p = add(3, 4);
- 00401497 push 4
- 00401499 push 3
- 0040149B call @ILT+15(add) (00401014)
- 004014A0 add esp,8
- 004014A3 mov dword ptr [ebp-4],eax
- template <typename type1, typename type2 = int>
- class data
- {
- type2 value;
- public:
- data(type2 m): value(m) {}
- ~data() {}
- };
- 239: data<int, int> m(2);
- 004013BD push 2
- 004013BF lea ecx,[ebp-10h]
- 004013C2 call @ILT+5(data<int,int>::data<int,int>) (0040100a)
- 004013C7 mov dword ptr [ebp-4],0
- 240: data<int> n(3);
- 004013CE push 3
- 004013D0 lea ecx,[ebp-14h]
- 004013D3 call @ILT+5(data<int,int>::data<int,int>) (0040100a)
明白了上面的缺省模板构造,下面我们谈一下特化模板。特化模板是什么意思呢?其实并不复杂。因为模板类既然是通用模板,那么其中的数据类型可以是任意数据类型,但是难免有一些数据类型(比如说指针),我们需要对其中的一些操作做一些细微的修改,但是这些小的修改在原来的模板定义上是无法做的。那么怎么办?我们只好重新定义一种形式,它和模板类定义的名称一致,但是形式稍有差别。我们可以编写一个测试看看:
- template <typename type>
- class data
- {
- public:
- data() {printf("normal!\n");}
- ~data() {printf("~normal!\n");}
- };
- template <>
- class data<int*>
- {
- public:
- data() {printf("point!\n");}
- ~data() {printf("point!\n");}
- };
- 249: data<int> p;
- 004013BD lea ecx,[ebp-10h]
- 004013C0 call @ILT+45(data<int>::data<int>) (00401032)
- 004013C5 mov dword ptr [ebp-4],0
- 250: data<int*> q;
- 004013CC lea ecx,[ebp-14h]
- 004013CF call @ILT+35(data<int *>::data<int *>) (00401028)
- 251: }
第一个变量的实际进入函数如下所示:
- 234: data() {printf("normal!\n");}
- 00401340 push ebp
- 00401341 mov ebp,esp
- 00401343 sub esp,44h
- 00401346 push ebx
- 00401347 push esi
- 00401348 push edi
- 00401349 push ecx
- 0040134A lea edi,[ebp-44h]
- 0040134D mov ecx,11h
- 00401352 mov eax,0CCCCCCCCh
- 00401357 rep stos dword ptr [edi]
- 00401359 pop ecx
- 0040135A mov dword ptr [ebp-4],ecx
- 0040135D push offset string "normal!\n" (0042607c)
- 00401362 call printf (00401540)
- 00401367 add esp,4
- 0040136A mov eax,dword ptr [ebp-4]
- 0040136D pop edi
- 0040136E pop esi
- 0040136F pop ebx
- 00401370 add esp,44h
- 00401373 cmp ebp,esp
- 00401375 call __chkesp (004023b0)
- 0040137A mov esp,ebp
- 0040137C pop ebp
- 0040137D ret
- 242: data() {printf("point!\n");}
- 00401430 push ebp
- 00401431 mov ebp,esp
- 00401433 sub esp,44h
- 00401436 push ebx
- 00401437 push esi
- 00401438 push edi
- 00401439 push ecx
- 0040143A lea edi,[ebp-44h]
- 0040143D mov ecx,11h
- 00401442 mov eax,0CCCCCCCCh
- 00401447 rep stos dword ptr [edi]
- 00401449 pop ecx
- 0040144A mov dword ptr [ebp-4],ecx
- 0040144D push offset string "point!\n" (00426074)
- 00401452 call printf (00401540)
- 00401457 add esp,4
- 0040145A mov eax,dword ptr [ebp-4]
- 0040145D pop edi
- 0040145E pop esi
- 0040145F pop ebx
- 00401460 add esp,44h
- 00401463 cmp ebp,esp
- 00401465 call __chkesp (004023b0)
- 0040146A mov esp,ebp
- 0040146C pop ebp
- 0040146D ret
思考题:
(1)模板类第一个type可以缺省吗?为什么会这么考虑?
(2)下面的代码在vc 6.0和vc 2005上都能编译过?为什么呢?对于我们设计代码有什么思考呢? (建议从兼容性上面考虑)
- template <typename type>
- class data
- {
- public:
- data() {printf("normal!\n");}
- ~data() {printf("~normal!\n");}
- };
- template <typename type>
- class data <type*>
- {
- public:
- data() {printf("point!\n");}
- ~data() {printf("point!\n");}
- };