函数模板:
C++另一种编程思想称为泛型编程,主要利用的技术就是模板
C++提供两种模板机制:函数模板和类模板
函数模板语法:
函数模板作用:
建立一个通用函数,其函数返回值类型和形参类型可以不具体制定,用一个虚拟的类型来代表。
语法:
template<typename T>
函数声明或定义
解释:
template --- 声明创建模板
typename --- 表面其后面的符号是一种数据类型,可以用class代替
T --- 通用的数据类型,名称可以替换,通常为大写字母
示例代码:
#include<iostream>
using namespace std;
template<typename T>
void mySwap(T& a, T& b) //利用传递的方式
{
T temp = a;
a = b;
b = temp;
}
void test01() {
//有两种种调用方式
int a = 10;
int b = 20;
//第一种自动类型推导
mySwap(a, b);
//第二种调用方式
mySwap<int>(a, b); //显示指定类型
cout << "a = " << a << endl;
cout << "b = " << b << endl;
}
int main() {
test01();
system("pause");
return 0;
}
总结:
1、函数模板利用关键字 template
2、使用函数模板有两种方式:自动类型推导、显示指定类型
3、模板的目的是为了提高复用性,将类型参数化
函数模板注意事项:
1、自动类型推导,必须推导出一致的数据类型T,才可以使用
示例代码:
#include<iostream>
using namespace std;
template<typename T>
void Swap(T &a, T &b) {
T temp;
temp = a;
a = b;
b = temp;
}
void test01() {
int a = 10;
int b = 20;
int c = 0.1;
//Swap(a,b); //正确
Swap(a, c);//错误
cout << "a = " << a << endl;
cout << "b = " << b << endl;
}
int main() {
test01();
system("pause");
return 0;
}
2、模板必须要确定出T的数据类型,才可以使用
示例代码:
#include<iostream>
using namespace std;
template<typename T>
void func() {
cout << "this is test" << endl;
}
void test01() {
// func(); 直接调用无法运行,我们必须要指定类型
func<int>();
}
int main() {
test01();
system("pause");
return 0;
}
普通函数与函数模板区别:
大家记住三句话就可以了
1、普通函数调用时可以发生自动类型转换(隐式类型转换)
2、函数模板调用时,如果利用自动类型推导,不会发生隐式类型转换
3、如果利用显示指定类型的方式,可以发生隐式类型转换
#include<iostream>
using namespace std;
template<class T>
int test01(T a, T b) {
return a + b;
}
int test02(int a,int b) {
return a + b;
}
int main() {
cout << test02(1, 2) << endl; //可以打印
cout << test02(1, 'a') << endl;//可打印
cout << test01(1, 2) << endl; //可以打印
cout << test01('a','a') << endl; //可以打印
//cout << test01(1, 'a') << endl; //不可以打印
cout << test01<int>(1, 'a') << endl; //可以打印
system("pause");
return 0;
}
普通函数与函数模板的调用规则:
#include<iostream>
using namespace std;
void test01(int a,int b) {
cout << "这是调用了普通函数" << endl;
}
template<class T>
void test01(T a, T b) {
cout << "这是调用了函数模板" << endl;
}
template<class T>
void test01(T a, T b, T c) {
cout << "这是调用了重载函数模板" << endl;
}
int main() {
test01(1, 1); //优先调用普通函数
test01<>(1, 1); //可以利用空模板的方式进行优先调用函数模板
test01(1, 2, 3); //函数模板可以进行重载
test01('a', 'b'); //函数模板如果可以产生更好的匹配,那么会优先调用函数模板
system("pause");
return 0;
}
总结:既然提供了函数模板,最好就不要提供普通函数,否则容易出现二义性
模板的具体化:
具体化的特点
1、具体化,显示具体化的原型和定意思以template<>开头,并通过名称来指出类型
2、具体化优先于常规模板
作用:当我们一个比较数值的函数模板,如果传入单个数值比较的话是可以的,但是如果我们传入的数值是一个数组,一个类的话那么就无法进行比较,C++为了解决这种问题,提供模板的重载,可以为这些特定的类型提供具体化的模板
示例代码:
#include<iostream>
#include<string>
using namespace std;
class Person {
public:
Person(string name,int age) {
this->m_age = age;
this->m_name = name;
}
public:
int m_age;
string m_name;
};
template<class T>
bool Compare(T a, T b) {
if (a == b) {
return true;
}else {
return false;
}
}
//具体化,显示具体化的原型和定意思以template<>开头,并通过名称来指出类型
//具体化优先于常规模板
template<> bool Compare(Person a, Person b) { //template<> 这种写法对Compare的函数模板进行模板具体化 传入的参数为Person,这里传入引用不引用其实都没关系,只是进行比较
if (a.m_age == b.m_age) {
return true;
}else {
return false;
}
}
int main() {
//int a = 1;
//int b = 2;
bool ret;
//ret = f1(a, b);
Person p1("adexx", 18);
Person p2("adedd", 19);
ret = Compare(p1, p2);
if (ret) {
cout << "true" << endl;
}else {
cout << "false" << endl;
}
system("pause");
return 0;
}