此文为FishC大佬《C++快速入门》第四十四讲函数模板的笔记整理。
到目前为止,我们已经介绍了两种C++程序设计范型,即:
在这一讲里,将介绍另一种范型:泛型编程!
泛型编程技术支持程序员创建函数和类的蓝图(即模板,template),而不是具体的函数和类。
这些模板可以没有任何类型:它们可以处理的数据并不仅限于某种特定的数据类型。
当程序需要用到这些函数中的某一个时,编译器将根据模板即时生成一个能够对特定数据类型进行处理的代码版本。
泛型编程技术可以让程序员用一个解决方案解决多个问题。
接下来的这几讲,我们先来学习如何编写和使用自己的泛型代码,然后阻碍跟大家介绍标准模板库(Standard Template Library,STL)。
在泛型编程技术里,我们仍然需要编写自己的函数和类,但不必限定它们所使用的数据类型。
只需要使用一个占位符(通常用字母T表示)然后用这个占位符来编写函数。
当程序需要这段代码时,你提供数据类型,编译器将根据你的模板即时生成实用的代码。
简单来说,编译器把模板里的每一个T替换成所提供的数据类型。
我们回来说说STL库,STL库是泛型编程技术的经典之作,它包含了许多非常有用的数据类型和算法。
以下代码定义了一个名为foo()的函数模板:
template
void foo(T param)
{
//do something
}
这里有几件事情值得注意:
- 第一行代码里:在尖括号里有一个class T,用来告诉编译器:字母T将在接下来的函数里代表一种不确定的数据类型。
- 关键字class并不意味着这是个类噢,这只是一种约定俗成的写法而已。
- 在告诉计算机T是一种类型之后,就可以像对待普通数据类型那样去使用它了。
举个栗子:
交换两个变量的值是一种几乎所有的程序都需要用到的基本操作。因为这种交换如此长剑,所以把它编写成一个函数。
void swap(int &a,int &b)
{
int tmp = a;
a = b;
b = tmp;
}
简单分析下:如果想用这个函数来交换两个double类型的变量的值,我们应该怎么办?
我们可以再增加一个swap(double &a,double &b)函数,因为C++支持函数重载。
但是我们发觉,不得不为交换的每一种数据类型反复编写同样的代码。
这正是函数末班大显身手的地方,你用不着为每种数据类型分别编写一个函数,只要告诉编译器你已经为此准备好了一个模板就行了!
这样子,等你再使用swap( )函数时,编译器将根据模板自动创建一个函数,该函数会使用正确的数据类型完成交换变量值的任务。
#include
#include
template
void swap(T &a, T &b)
{
T tmp = a;
a = b;
b = tmp;
}
int main()
{
int i1 = 100;
int i2 = 200;
std::cout << "交换前, i1 = " << i1 << ", i2 = " << i2 << "\n";
swap(i1, i2);
std::cout << "交换后, i1 = " << i1 << ", i2 = " << i2 << "\n";
std::string s1 = "小甲鱼";
std::string s2 = "小由鱼";
std::cout << "交换前, s1 = " << s1 << ", s2 = " << s2 << "\n";
swap(s1, s2);
std::cout << "交换后, s1 = " << s1 << ", s2 = " << s2 << "\n";
return 0;
}
神器的函数模板!简直是偷懒神器。
在创建模板时,还可以用template
再强调一次,不要把函数模板分成原型和实现两个部分。如果编译器看不到模板的完整代码,它就无法正确的生成代码。
为了明确表明swap( )是一个函数模板,还可以使用swap
如果某个函数对所有数据类型都将进行同样的处理,就应该把它编写成一个模板。
如果某个函数对不同的数据类型将进行不同的处理,就应该对它进行重载。