【笨木头C++】基与基础12:函数模板(下)

笨木头  2015-01-7 21:16   其它   阅读(2,782)   6条评论

 

最近突然想研究研究Unity3D了,于是我就开始去研究了,希望坑别太大,比Cocos2d-x少就好。

我也很久没有出新游戏了,因为我最近在写一个网站,有个点子,一直没敢跨出第一步,现在总算跨出了。

为什么用网站来实现?不知道,可能好玩吧…

 

咳咳,跑题了,上一篇简单介绍了C++的函数模板,说实话,我很少用(小若:呸~!你就从来没用过!)

今天来继续把函数模板更高级的用法介绍一下。

 

 

笨木头花心贡献,啥?花心?不呢,是用心~

转载请注明,原文地址:http://www.benmutou.com/archives/1941

文章来源:笨木头与游戏开发

 

 

1.我也能重载——函数模板的重载

既然是函数,当然就拥有重载的功能了。

有时候同一个函数模板,可能有不一样的参数,比如:


1
2
3
4
5
6
7
8
9
10
11
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";
}

这样,虽然都是getDouble函数模板,但是传入的参数数量不一样,就可以得到不同的结果。

和普通的函数重载没有什么太大的区别,不多解释。

 

2.特殊情况——模板的缺陷

如果你是一位比较神经病的人的话,你一定有一个疑惑——如果我调用getDouble的时候,传一个类进去作为参数,结果会怎么样呢?

结果当然是…会报错啊喂,一般情况下,类对象是不能做乘法操作的。

 

那如果我就是要传一个类进去呢?

没关系,C++的特点就是——够复杂,任性。

你想要的,它都能给你,也因此变得很复杂。(小若:那算了,我们就这样结束这篇文章吧)

 

3.显示具体化

为了解决特殊情况,我们可以直接给函数模板定义其中一种实现。

如下代码:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#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;
}

运行这段代码,输出:

神经病,我要数字,不要类!

 

我们来回顾一下,函数模板的工作原理:

1.我们在调用getDouble函数的时候,编译器会把传入的参数类型替换掉模板里的T,生成一个函数。

2.相当于我们手动编写了一个函数,只不过是编译器帮我们写了。

3.调用getDouble时,传入的参数类型不同,就会生成不同的函数。

 

所以,当我们调用getDouble(new Mutou())时,会生成这样一个函数:


1
2
3
4
void getDouble(Mutou* num)
{
    std::cout << (num * 2) << "\n";
}

但很显然,num*2在这里是无法执行的。

 

于是,我们需要特殊对待,专门为Mutou*参数写一个函数来处理,结果就有了【template<> void getDouble(Mutou* num)】。

相当于在普通函数前面加了【template<>】 前缀。

 

为什么要加这个前缀?不加不行吗?就直接添加一个getDouble(Mutou* num)函数不是好好的吗?

(小若:对吖对吖,是不是可以省略这个前缀?)

才不是~!因为getDouble已经被声明为一个函数模板了,如果这时候我们又定义一个普通的getDouble函数,会让编译器混乱的。

没错,原因仅仅是因为它会混乱,所以我们必须加点东西在函数前面,让编译器可以识别出来。

 

最终,我们调用getDouble(new Mutou())时,就会优先使用后面声明的getDouble函数,而编译器也不会使用Mutou类型来创建一个getDouble函数。

 

4.结束

好了,其实还有一个叫做【显示实例化】的东西,这个是用在函数调用时的,解释起来又要和【显示具体化】做对比。

太烦了,一般也用不上,都是写搞特殊的东西。

今天写文章耗时有点多,就到此为止咯。

 

6 评论

发表评论

电子邮件地址不会被公开。 必填项已用*标注