一、什么是模板
C++中的模板分为类模板和函数模板,并不是一个实际的类或函数,这指的是编译器不会自动为其生成具体的可执行代码。只有在具体执行时,编译器才帮助其实例化。
二、为什么引入模板
拿我们最常见的交换函数来举例子,如果我们编写一个交换int类型变量的函数,如下:
bool Swap(int &a, int &b) {
int c = a;
a = b;
b = c;
return true;
}
但如果我们想要编写一个通过函数来交换float的函数,我们又要写另一个函数,如下:
bool Swap(float &a, float &b) {
float c = a;
a = b;
b = c;
return true;
}
那接下来如果需要交换double,char,bool,甚至一些结构体或者类的交换函数,那么我们的工作量就会很大。细心观察会发现,其实上边两个函数唯一不同的便是交换的变量类型不同,如果我们把变量类型设置为一个抽象的X,在具体需要交换的时候,再去根据具体的类型去自动适应,这便是C++的template模板的巧妙之处。
三、使用方式
C++模板采用template关键字修饰
3.1 函数模板
具体写法如下:
template <typename 参数类型1, typename 参数类型2,...>
返回值类型 函数名称(形参1, 形参2,...) {
函数体
}
上边代码的typename关键字也可以用class代替。下边给出一个交换函数模板的例子:
template <typename T>
bool Swap(T &a, T &b) {
T c = a;
a = b;
b = c;
return true;
}
3.2 类模板
具体写法如下:
template <typename 模板名称1, typename 模板名称2,...>
class 类名称{
类成员
}
注意,在实例化类模板对象时,需要在类的结尾加上<具体模板名称>。 比如以下例子:
template <typename T1, typename T2>
class NNUM {
private :
T1 num1;
T1 num2;
public :
NNUM(T1 num1, T1 num2) {
this->num1 = num1;
this->num2 = num2;
}
void print_NNUM(T2 str) {
cout << "str : [" << str << "]" << endl;
cout << "num1 : <" << this->num1 << ">, " << "num2 : <" << num2 << ">" << endl;
}
};
这里是一个用了2个模板类型(T1和T2)的类模板,那么我们在实例化时候就要按照以下代码,将具体需要使用的T1与T2类型体现出来:
NNUM<int, string> n1 = NNUM<int, string>(123, 456);
四、模板函数和普通函数的区别
区别在于是否会发生隐式类型转换。例子如下:
/*函数模板*/
template <typename T>
T fun1(T num1, T num2) {
return num1 * num2;
}
/*普通函数*/
float fun2(float num1, float num2) {
return num1 * num2;
}
int main() {
int x = 222;
float y = 3.0;
/*函数模板*/
//以下这条语句报错,因为函数模板无法隐式地将int类型的x转换为float类型
//cout << fun1(x, y) << endl; //语句1
/*普通函数*/
//这条语句正确 222.0 * 3.0 = 666.0
cout << fun2(x, y) << endl; //语句2
//以下这条语句正确,因为显示调用函数模板,可以实现自动类型转换
cout << fun1<float>(x, y) << endl; //语句3
return 0;
}
以上代码中,fun1为函数模板,fun2为普通函数。
当使用函数模板传入的参数为int和double时,语句1报错,因为函数模板无法隐式地将int类型的x转换为float类型,无法完成隐式自动转换。同样的使用放入fun2的普通函数中就可以正常运行和输出。语句3采用显示调用的方式,同样也可以实现自动类型转换。

833

被折叠的 条评论
为什么被折叠?



