C++模板初阶
Posted 山舟
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++模板初阶相关的知识,希望对你有一定的参考价值。
一、泛型编程
以交换两个变量的值为例:
代码如下:
void Swap(int& a, int& b)
{
int temp = a;
a = b;
b = temp;
}
void Swap(double& a, double& b)
{
double temp = a;
a = b;
b = temp;
}
void Swap(char& a, char& b)
{
char temp = a;
a = b;
b = temp;
}
//同理可写出unsigned int,float……类型的交换函数
函数重载可以存在多个同名的Swap函数、引用的使用已经比C语言已经方便了很多,但是以下两个方面仍很难处理:
(1)重载的函数仅仅只是类型不同,而逻辑完全相同,代码的复用率比较低,只要有新类型出现,就需要增加对应的函数。
(2)代码的可维护性比较低,由于逻辑相同,一个出错所有的重载均出错。
那能否告诉编译器一个模子,让编译器根据不同的类型利用该模子来生成代码呢?
C++提供模板template来实现。
二、函数模板
1.函数模板概念
函数模板代表了一个函数集合,该函数模板与类型无关,在使用时被参数化,根据实参类型产生适用于不同类型的函数。
2.函数模板格式
template<typename T1, typename T2,…,typename Tn>
返回值类型 函数名(参数列表){}
具体写法如下:
//T也可为其它名称
template<typename T>//注意没有逗号
void Swap(T& left, T& right)
{
T temp = left;
left = right;
right = temp;
}
int main()
{
//下面的Swap函数时两个不同的函数,因为他们的参数列表不同
//一个参数是两个int,另一个的参数是两个double
int a = 1, b = 2;
Swap(a, b);
double c = 3.14, d = 3.15;
Swap(c, d);
return 0;
}
调试查看反汇编代码,发现函数地址不同,显然是两个不同的函数。
查看反汇编结果如下:
typename是用来定义模板参数关键字的,也可以使用class,但切记不能使用struct代替class。
注意一个模板只能在之后的第一个函数中使用,剩余的函数无法再使用。
template<class X>
void Swap(X& a, X& b)
{
X tmp = a;
a = b;
b = tmp;
}
void f(X a)//error
{}
3.函数模板的实例化
代码如下:
template<class T>
T add(T a, T b)
{
return a + b;
}
int main()
{
int a = 1, b = 2;
add(a, b);//√
double c = 3.14, d = 3.15;
add(c, d);//√
add(a, c);//error
//该语句无法通过编译,编译器通过a推演得出T应为int,但通过c推演得出T应为double
//二者矛盾,编译器无法确定T到底应该是哪一种类型,报错
//以下两种办法可以解决
//1.强制类型转换
add(a, (int)c);
//2.显式实例化:在函数名后的<>中指定模板参数的类型
add<int>(a, c);
add<double>(a, c);
return 0;
}
三、类模板
1.类模板的定义
以顺序表为例,在C语言中,通过下面的方式使代码面对不同类型的数据时尽可能复用。
代码如下:
typedef int DataType;
struct Vector
{
DataType _a;
int _size;
int _capacity;
};
//对顺序表的操作函数
//...
但是这也有一个问题,就是在同一份代码中,无法同时创建一个数据类型为int的顺序表和一个数据类型为double的顺序表,如果想要实现,又需要重写一份几乎完全相同的代码。
C++中可使用类模板来解决上述问题。
代码如下:
template<class T>
class Vector
{
public:
//成员函数
//...
private:
T* _a;
int _size;
int _capacity;
};
int main()
{
Vector<int> v1;//数据类型为int的顺序表v1
Vector<double> v2;//数据类型为double的顺序表v2
return 0;
}
2.类模板的实例化
类模板实例化与函数模板实例化不同,类模板实例化需要在类模板名字后跟<>,然后将实例化的类型放在<>中即可,类模板名字不是真正的类,实例化的结果才是真正的类。
上面的代码中Vector是类名,Vector < int >才是类型。
模板不支持分离编译,也就是说声明放在.h文件中,而定义放在.cpp中。
感谢阅读,如有错误请批评指正
以上是关于C++模板初阶的主要内容,如果未能解决你的问题,请参考以下文章