最近在看 C++ 的方法和类模板,我就在想 C# 中也是有这个概念的,叫泛型.
一、类模板 template
C++ 标准:
template
template
实际情况:
二者都可以用于各种数据类型。
Bjarne.Stroustrup说:
The 'typename' keyword can also be used as an alternative to 'class' in template declarations. For example:
template
Being an indifferent typist and always short of screen space, I prefer the shorter:
template
特例:
当T是一个类,而这个类又有子类(假设名为 innerClass) 时,应该用 template
typename T::innerClass myInnerObject;
这里的 typename 告诉编译器,T::innerClass 是一个类,程序要声明一个 T::innerClass 类的对象,而不是声明 T 的静态成员,而 typename 如果换成 class 则语法错误。
模板是实现代码重用机制的一种工具,实质就是实现类型参数化,即把类型定义为参数。C++提供两种模板:函数模板,类模板。
函数模板
#include "stdafx.h" #includeusing namespace std; template // 或者 template T my_max(T a, T b) { return a>b ? a : b; } int main() { int nresult = my_max(10, 25); char nresult2 = my_max('a', 'b'); cout << "nresult=" << nresult << "nnresult2=" << nresult2 << endl; return 0; }
类模板
#include "stdafx.h" #includeusing namespace std; template // 或者 template class CMax { public: CMax(T a, T b) { m_a = a; m_b = b; } T GetMax() { return m_a > m_b ? m_a : m_b; } private: T m_a; T m_b; }; int main() { CMax myMax(10,25); int nresult = myMax.GetMax(); CMax myMax2('a', 'b'); char nresult2 = myMax2.GetMax(); cout << "nresult=" << nresult << "nnresult2=" << nresult2 << endl; return 0; }
二、C++ 中的模板具体玩法
毕竟 C++ 是兼容 C 语言,而 C 是过程式的玩法,所以 C++ 就出现了两种模板类型,分别为:函数模板 和 类模板,下面简单分析一下。
1. 函数模板的玩法
玩之前先看看格式: template
说实话,我感觉 C++ 这一点就做的非常好,人家在开头就特别强调了,这是一个 template,大家不要搞错了,按照这个格式,我们来一个简单的 Sum 操作,参考代码如下:
#include//求和函数 template T getsum(T t1, T t2) { return t1 + t2; } int main() { int sum1 = getsum (10, 10); long sum2 = getsum (20, 20); printf("output: int:sum=%d, long: sum=%ld", sum1, sum2); }
我就很好奇,这种玩法和 普通方法 调用有什么不同,要想找到答案,可以用 IDA 去看它的静态汇编代码。
从静态反汇编代码看,当前生成了两个函数符号分别为: j_??$getsum@H@@YAHHH@Z 和 j_??$getsum@J@@YAJJJ@Z,现在我们就搞清楚了,原来一旦给 模板 指定了具体类型,它就生成了一个新的函数符号。
乍一看这句话好像没什么问题,但如果你心比较细的话,会发现一个问题,如果我调用两次 getsum
int main()
{
int sum1 = getsum
int sum2 = getsum
}
然后再用 IDA 查看一下。
哈哈,可以发现这时候并没有生成一个新的函数符号,其实往细处说:j_??$getsum@H@@YAHHH@Z 是函数签名组合出来的名字,因为它们签名一致,所以在编译阶段必然就一个了。
2. 类模板的玩法
首先看下类模板的格式:template
#includetemplate class Calculator { public: T getsum(T a1, T b1) { return a1 + b1; } }; int main() { Calculator cal1; int sum1 = cal1.getsum(10, 10); Calculator cal2; int sum2 = cal2.getsum(15, 15); printf("output: sum1=%d, sum2=%ld", sum1,sum2); }
接下来直接看 IDA 生成的汇编代码。
从上面的方法签名组织上看,有点意思,类名+方法名 柔和到一个函数符号上去了,可以看到符号不一样,说明也是根据模板实例化出的两个方法。



