最近突然想研究研究Unity3D了,于是我就开始去研究了,希望坑别太大,比Cocos2d-x少就好。
我也很久没有出新游戏了,因为我最近在写一个网站,有个点子,一直没敢跨出第一步,现在总算跨出了。
为什么用网站来实现?不知道,可能好玩吧...
咳咳,跑题了,上一篇简单介绍了C++的函数模板,说实话,我很少用
(小若:呸~!你就从来没用过!)今天来继续把函数模板更高级的用法介绍一下。
笨木头花心贡献,啥?花心?不呢,是用心~
转载请注明,原文地址:http://www.benmutou.com/archives/1941
文章来源:笨木头与游戏开发
1.我也能重载——函数模板的重载
既然是函数,当然就拥有重载的功能了。
有时候同一个函数模板,可能有不一样的参数,比如:
[cce_cpp]
template <typename T>
void getDouble(T num)
{
std::cout << (num * 2) << "\n";
}
template <typename T>
void getDouble(T num1, T num2)
{
std::cout << (num1 * num2) << "\n";
}
[/cce_cpp]
这样,虽然都是getDouble函数模板,但是传入的参数数量不一样,就可以得到不同的结果。
和普通的函数重载没有什么太大的区别,不多解释。
2.特殊情况——模板的缺陷
如果你是一位比较神经病的人的话,你一定有一个疑惑——如果我调用getDouble的时候,传一个类进去作为参数,结果会怎么样呢?
结果当然是...会报错啊喂,一般情况下,类对象是不能做乘法操作的。
那如果我就是要传一个类进去呢?
没关系,C++的特点就是——够复杂,任性。
你想要的,它都能给你,也因此变得很复杂。
(小若:那算了,我们就这样结束这篇文章吧)
3.显示具体化
为了解决特殊情况,我们可以直接给函数模板定义其中一种实现。
如下代码:
[cce_cpp]
#include "stdafx.h"
#include "iostream"
/* 一个类 */
class Mutou {
};
/* 定义函数模板 */
template <typename T>
void getDouble(T num)
{
std::cout << (num * 2) << "\n";
}
/* 具体实现某种类型的函数 */
template<> void getDouble(Mutou* num)
{
std::cout << "神经病,我要数字,不要类!" << "\n";
}
int _tmain(int argc, _TCHAR* argv[])
{
getDouble(new Mutou());
return 0;
}
[/cce_cpp]
运行这段代码,输出:
神经病,我要数字,不要类! 我们来回顾一下,函数模板的工作原理:
1.我们在调用getDouble函数的时候,编译器会把传入的参数类型替换掉模板里的T,生成一个函数。
2.相当于我们手动编写了一个函数,只不过是编译器帮我们写了。
3.调用getDouble时,传入的参数类型不同,就会生成不同的函数。
所以,当我们调用getDouble(new Mutou())时,会生成这样一个函数:
[cce_cpp]
void getDouble(Mutou* num)
{
std::cout << (num * 2) << "\n";
}
[/cce_cpp]
但很显然,num*2在这里是无法执行的。
于是,我们需要特殊对待,专门为Mutou*参数写一个函数来处理,结果就有了【template<> void getDouble(Mutou* num)】。
相当于在普通函数前面加了【template<>】 前缀。
为什么要加这个前缀?不加不行吗?就直接添加一个getDouble(Mutou* num)函数不是好好的吗?
(小若:对吖对吖,是不是可以省略这个前缀?)才不是~!因为getDouble已经被声明为一个函数模板了,如果这时候我们又定义一个普通的getDouble函数,会让编译器混乱的。
没错,原因仅仅是因为它会混乱,所以我们必须加点东西在函数前面,让编译器可以识别出来。
最终,我们调用getDouble(new Mutou())时,就会优先使用后面声明的getDouble函数,而编译器也不会使用Mutou类型来创建一个getDouble函数。
4.结束
好了,其实还有一个叫做【显示实例化】的东西,这个是用在函数调用时的,解释起来又要和【显示具体化】做对比。
太烦了,一般也用不上,都是写搞特殊的东西。
今天写文章耗时有点多,就到此为止咯。