函数模版(泛型编程)
为什么要有函数模版?
函数模版本质: 类型参数化
函数模版定义形式:
template <类型形式参数表>
类型形式参数形式为: typename T1, typename T2, … 或 class T1, class T2, …
函数模版声明:
template <类型形式参数表>
类型 函数名(形式参数表)
{
语句序列
}
- 函数模版定义由模版说明和函数定义组成
- 模版说明的类属参数必须在函数定义中至少出现一次
- 函数参数表中可以使用类属类型参数,也可以使用一般类型参数
template 告诉C++编译器, 开始泛型编程, 看到T,不报错
template <typename T>
void myswap(T &a, T &b)
{
}
函数模版的调用
- 显示类型调用
- 自动类型推导
函数模版遇上函数重载
- 函数模版不允许自动类型转化,普通函数能够进行自动类型转化
- 普通函数的调用:可以进行隐式的类型转换
- 函数模版函数的调用(本质:类型参数化):将严格的按照类型进行匹配,不会进行自动类型转换
template <typename T>
void myswap(T &a, T &b)
{
T c = 0;
c = a;
a = b;
b = c;
}
void myswap(int a, char c)
{
cout << "a: " << a << endl;
}
void main()
{
int a = 10;
char c = "z";
}
- 函数模版可以做普通函数一样被重载
- C++编译器优先考虑普通函数
- 如果函数模版可以产生一个更好的匹配,那么选择模版
- 可以通过空模版实参列表的语法限定编译器只通过模版匹配
重载:发生在同一个作用域,同一个类
重写:父子类之间,一个虚函数产生多态,不是虚函数重写则发生重定义
思考:为什么函数模版可以和函数重载放在一起,C++编译器是如何提供函数模版机制的?
答:
1、编译器并不是把函数模版处理成能够处理任意类型的函数
2、编译器从函数模版通过具体类型产生不同的函数
3、编译器会对函数模版进行两次编译,在声明的地方对模版代码本身进行编译;在调用的地方对参数替换后的代码进行编译。
编译器编译原理