最近在看 C++ 的方法和类模板,我就在想 C# 中也是有这个概念的,不过叫法不一样,人家叫模板,我们叫泛型,哈哈,有点意思,这一篇我们来聊聊它们底层是怎么玩的?
一:C++ 中的模板玩法
毕竟 C++ 是兼容 C 语言,而 C 是过程式的玩法,所以 C++ 就出现了两种模板类型,分别为:函数模板
和 类模板
,下面简单分析一下。
1. 函数模板的玩法
玩之前先看看格式: template <typename T> rettype funcname (parameter list) { }
。
说实话,我感觉 C++ 这一点就做的非常好,人家在开头就特别强调了,这是一个 template
,大家不要搞错了,按照这个格式,我们来一个简单的 Sum
操作,参考代码如下:
#include <iostream>
//求和函数
template <typename T> T getsum(T t1, T t2) {
return t1 + t2;
}
int main() {
int sum1 = getsum<int>(10, 10);
long sum2 = getsum<long>(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>
方法,那会生成两个具体函数吗? 为了寻找答案,我们修改下代码:
int main() {
int sum1 = getsum<int>(10, 10);
int sum2 = getsum<int>(15, 15);
}
然后再用 IDA 查看一下。
哈哈,可以发现这时候并没有生成一个新的函数符号
,其实往细处说:j_??$getsum@H@@YAHHH@Z
是函数签名
组合出来的名字,因为它们签名一致,所以在编译阶段必然就一个了。
2. 类模板的玩法
首先看下类模板的格式:template <typename T1, typename T2, …> class className { };
还是那句话,开头一个 template
暴击,告诉你这是一个模板
请发表评论