C++函数模板
C++另一种编程思想称为泛型编程,主要采用的技术就是模板
C++提供两种模板机制:函数模板和类模板。本片文章我们介绍一下函数模板。类模板看另外一篇C++类模板
一、函数模板
1、作用
建立一个通用函数,其函数返回值和形参类型可以不具体制定。用一个虚拟的类型来表示
2、语法
template<typename T>
函数声明或定义
template——声明模板
typename——表明后面的符号是一种数据类型,可以用class来代替
T——通用的数据类型,可以替换,但一般都是大写字母
3、注意事项
1、自动类型推导,必须要推导出一致的数据类型T才可以使用
2、模板必须要确定T的数据类型才可以使用
下面的例子来解释上面:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5;
template<class T>
void swapp(T &a ,T &b)
{
T tmp=a;
a=b;
b=tmp;
}
template<class T>
void fun()
{
cout<<"I am fine"<<endl;
}
int main()
{
int a=10,b=20;
char c='c';
//使用函数模板第一种方式:自动类型推导
//swapp(a,b);
//使用函数模板的第二种方式:显式指定类型,这种方法可以发生隐式类型转换
swapp<int>(a,b);
//自动类型推导,必须要推导出一致的数据类型T才可以使用
//swapp(a,c); 报错
//模板必须要推导出确定的T的数据类型,才可以使用
//fun(); //报错,模板不知道数据类型T
fun<int>(); //正确,随便给一个数据类型就可以
printf("%d %d\n",a,b);
return 0;
}
二、普通函数与函数模板的调用规则
1、如果普通函数和函数模板都可以实现,优先调用普通函数
//如果普通函数和函数模板都可以实现,优先调用普通函数
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5;
template<class T>
void swapp(T a ,T b)
{
cout<<"function template"<<endl;
}
void swapp(int a ,int b); //如果只有函数声明没有函数实现,会报错
// void swapp(int a ,int b) //如果这个函数存在,那么先调用这个函数
// {
// cout<<"simple template"<<endl;
// }
int main()
{
int a=10,b=20;
swapp(a,b);
return 0;
}
2、可以利用空模板参数列表来强制调用函数模板
//可以利用空模板参数列表来强制调用函数模板
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5;
template<class T>
void swapp(T a ,T b)
{
cout<<"function template"<<endl;
}
void swapp(int a ,int b); //不会报错,因为偶没有调用这个函数
// void swapp(int a ,int b) //如果这个函数存在,那么先调用函数模板
// {
// cout<<"simple template"<<endl;
// }
int main()
{
int a=10,b=20;
//通过空模板参数列表就可以的强制调用函数模板
swapp<>(a,b);
return 0;
}
3、函数模板也可以发生重载
4、如果函数模板可以产生更好的匹配,优先调用函数模板
//如果函数模板可以产生更好的匹配,优先调用函数模板
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5;
template<class T>
void swapp(T a ,T b)
{
cout<<"function template"<<endl;
}
void swapp(int a ,int b); //不会报错,因为没有调用这个函数
// void swapp(int a ,int b) //如果这个函数存在,那么先调用函数模板
// {
// cout<<"simple template"<<endl;
// }
int main()
{
char a=10,b=20;
//因为调用普通函数需要发生隐式类型转换(char->int),而调用函数模板就不需要
swapp(a,b);
return 0;
}
三、模板的局限性
有些特定数据类型,需要用具体换方式做特殊实现
#include <bits/stdc++.h> using namespace std; class Person { public: Person(string name, int age) { this->m_Name = name; this->m_Age = age; } string m_Name; int m_Age; }; //普通函数模板 template <class T> bool myCompare(T &a, T &b) { if (a == b) { return true; } else { return false; } } //具体化,显示具体化的原型和定意思以template<>开头,并通过名称来指出类型 //具体化优先于常规模板 template <> bool myCompare(Person &p1, Person &p2) { if (p1.m_Name == p2.m_Name && p1.m_Age == p2.m_Age) { return true; } else { return false; } } void test01() { int a = 10; int b = 20; //内置数据类型可以直接使用通用的函数模板 bool ret = myCompare(a, b); if (ret) { cout << "a == b " << endl; } else { cout << "a != b " << endl; } } void test02() { Person p1("Tom", 10); Person p2("Tom", 10); //自定义数据类型,不会调用普通的函数模板 //可以创建具体化的Person数据类型的模板,用于特殊处理这个类型 bool ret = myCompare(p1, p2); if (ret) { cout << "p1 == p2 " << endl; } else { cout << "p1 != p2 " << endl; } } int main() { test01(); test02(); system("pause"); return 0; }