模板是什么
模板大家都知道,比如我们找工作的时候需要做简历,简历里面有些东西是写好的,比如姓名、年龄等,这些定义好的东西,只需要我们将自己的信息填进去就行,不需要再去写上姓名或者年龄这些字样。这就是模板。C++中的模板也是这样的功能,模板作为一个搭建好的框架,可以很方便的帮助我们进行编程。C++中的模板主要分为函数模板和类模板两类。
函数模板
函数模板不是一个实实在在的函数,有点滑头,函数模板只是一个对函数制定一个功能框架,它的函数返回值类型和形参类型都是没有进行具体制定的,这个类型是一个虚拟的类型。
template <typename T>
template是关键词,表示定义或声明创建了一个模板;
typename表示它后面的是一个数据类型,可以和class替换;
T表示通用的数据类型,名称可以替换,一般为大写字母;
一般用法是这样的:
template <class T>
void test(T t)
{
//函数实现内容
}
为什么要定义函数模板呢?我们来看一个加法代码:
#include<iostream>
using namespace std;
int add01(int& a, int& b)
{
return a + b;
}
double add02(double& a, double& b)
{
return a + b;
}
void test01()
{
int a = 10, b = 20;
int temp01 = add01(a, b);
cout << "a与b的和是:" << temp01 << endl;
double c = 0.1, d = 0.2;
double temp02 = add02(c, d);
cout << "c与d的和是:" << temp02 << endl;
}
void main()
{
test01();
}
这是一个很简单的加法代码,整型与整型相加,浮点与浮点相加,但是数据类型有那么多种,如果一个一个写来的话,岂不是很麻烦。因此定义一个通用的函数模板,简化代码:
#include<iostream>
using namespace std;
int add01(int& a, int& b)
{
return a + b;
}
double add02(double& a, double& b)
{
return a + b;
}
//此处定义函数模板
template<typename T>
T newadd(T& a, T& b)
{
return a + b;
}
void test01()
{
int a = 10, b = 20;
int temp01 = add01(a, b);
cout << "a与b的和是:" << temp01 << endl;
double c = 0.1, d = 0.2;
double temp02 = add02(c, d);
cout << "c与d的和是:" << temp02 << endl;
}
void main()
{
test01();
int a = 100, b = 200;
int temp = newadd(a, b);
cout << "a与b的和是:" << temp << endl;
}
在定义好了函数模板之后,T作为参数类型和返回值类型,各种类型的加法函数都可以进行通过“T类型的函数”来得到其返回值。当然,我们可以显示指定的类型,:
int temp = newadd<int>(a, b);
在使用函数模板的时候,一定要推导出具有相同类型的T才可以使用,所定义的模板要确定好了T的类型之后,才可以使用。
下面这个例子是通过定义函数模板实现数组中的数组从大到小排列的。
#include<iostream>
using namespace std;
template<class T>
void mySwap(T& a, T& b)
{
T temp = a;
a = b;
b = temp;
}
template<class T>
void mySort(T arr[], int len)
{
for (int i = 0; i < len; i++)
{
int max = i;
for (int j = i + 1; j < len; j++)
{
if (arr[max] < arr[j])
{
max = j;
}
}
if (max != i)
{
mySwap(arr[max], arr[i]);
}
}
}
template <class T>
void printArr(T arr[],int len)
{
for (int i = 0; i < len; i++)
{
cout << arr[i] << " ";
}
cout <<endl;
}
void test()
{
char array[] = "ddsajhdk";
int length = sizeof(array) / sizeof(char);
mySort(array, length);
printArr(array, length);
}
int main()
{
test();
}
普通函数和函数模板一起出现的时候,该怎么调用呢?如果说二者同名且都可以实现目标功能,那么会优先调用普通函数,当然,也可以通过空模板参数列表来强制调用函数模板。
#include <iostream>
using namespace std;
void normal(int &a)
{
cout << "我是普通函数" << endl;
}
template <class T>
void normal(T& a)
{
cout << "我是模板函数" << endl;
}
void test()
{
int a = 10;
normal(a);
}
void main()
{
test();
}
输出结果为:
当我们将普通函数只做声明时候,这时候的编译器就会报错,这时候就需要通过空模板参数列表来对函数模板进行强制调用。
#include <iostream>
using namespace std;
void normal(int& a);
//{
// cout << "我是普通函数" << endl;
//}
template <class T>
void normal(T& a)
{
cout << "我是模板函数" << endl;
}
void test()
{
int a = 10;
//normal(a);
normal<>(a);//通过空模板参数列表进行强制调用
}
void main()
{
test();
}
还有一点就是函数模板的重载,当我们的普通函数为一个参数,函数模板中为两个参数时,即发生了函数重载,这个根据参数就可以判断出执行哪一个函数。
#include <iostream>
using namespace std;
void normal(int& a)
{
cout << "我是普通函数" << endl;
}
template <class T>
void normal(T& a, T b)
{
cout << "我是重载模板函数" << endl;
}
void test()
{
int a = 10;
//normal(a);
//normal<>(a);//通过空模板参数列表进行强制调用
normal(a, 10);
}
void main()
{
test();
}
运行结果是:
除了上面的情况外,在调用到自定义类型的参数的时候,函数模板会出现不识别的情况,这时候就需要对函数模板进行重载。
#include <iostream>
#include<string>
using namespace std;
class Car
{
public:
Car(string name, int price)
{
this->C_name = name;
this->C_price = price;
}
string C_name; //车的品牌名
int C_price;//车的价格
};
template<class T>
void Swap(T& a, T& b)
{
T temp = a;
a = b;
b = temp;
}
//开始进行函数模板的重载
template<>void Swap(Car& p1, Car& p2) //注意前面要加上 template<>
{
int temp = p1.C_price;
p1.C_price = p2.C_price;
p2.C_price = temp;
}
void test()
{
int a = 10;
int b = 20;
Swap(a, b);
cout << "a=" << a << endl;
cout << "b=" << b << endl;
}
void test01()
{
//实现车价格的交换
//但是直接将一个Car类型的数据传入到模板不识别
//因此需要我们重载函数模板
Car car1 = {"宝马",100};
Car car2 = { "奔驰",200 };
Swap(car1, car2);
cout << "car1的价格是:" << car1.C_price << endl;
cout << "car2的价格是:" << car2.C_price << endl;
}
void main()
{
test();
test01();
}
以上就是 函数模板的学习,下一篇会进行类模板的学习,希望可以帮助到大家!