代码编译运行环境:VS2017+Debug+Win32
文章目录
模板的实例化指函数模板(类模板)生成模板函数(模板类)的过程。对于函数模板而言,模板实例化之后,会生成一个真正的函数。而类模板经过实例化之后,只是完成了类的定义,模板类的成员函数需要到调用时才会被初始化。模板的实例化分为隐式实例化和显示实例化。
对函数模板的使用而言,分为两种调用方式,一种是显示模板实参调用(显示调用),一种是隐式模板实参调用(隐式调用)。对于类模板的使用而言,没有隐式模板实参和显式模板实参使用的说法,因为类模板的使用必须显示指明模板实参。各个概念请勿混淆。
1.隐式实例化
这是相对于模板显示实例化而言。在使用模板函数和模板类时,不存在指定类型的模板函数和模板类的实体时,由编译器根据指定类型参数隐式生成模板函数或者模板类的实体称之为模板的隐式实例化。
1.1 函数模板隐式实例化
函数模板隐式实例化指的是在发生函数调用的时候,如果没有发现相匹配的函数存在,编译器就会寻找同名函数模板,如果可以成功进行参数类型推演,就对函数模板进行实例化。
还有一种间接调用函数的情况,也可以完成函数模板的实例化。所谓的间接调用是指将函数入口地址传给一个函数指针,通过函数指针完成函数调用。如果传递给函数指针不是一个真正的函数,那么编译器就会寻找同名的函数模板进行参数推演,进而完成函数模板的实例化。参考如下示例。
#include <iostream>
using namespace std;
template <typename T> void func(T t) {
cout<<t<<endl;
}
void invoke(void (*p)(int)) {
int num=10;
p(num);
}
int main() {
invoke(func);
}
程序成功运行并输出10。
1.2 类模板隐式实例化
类模板隐式实例化指的是在使用模板类时才将模板实例化,相对于类模板显示实例化而言的。
#include <iostream>
using namespace std;
template<typename T>class A {
T num;
public:
A() {
num=T(6.6);
}
void print() {
cout<<"A'num:"<<num<<endl;
}
};
int main() {
A<int> a; //显示模板实参的隐式实例化
a.print();
}
程序输出结果:A’num:6。
2.显示实例化
显示实例化也称为外部实例化。在不发生函数调用的时候将函数模板实例化,或者在不使用类模板的时候将类模板实例化称之为模板显示实例化。
2.1 函数模板显示实例化
对于函数模板而言,不管是否发生函数调用,都可以通过显示实例化声明实例化函数模板。
template [函数返回类型] [函数模板名]<实际类型列表>(函数参数列表);
// 如
template void func<int>(const int&);
2.2 类模板显示实例化
对于类模板而言,不管是否生成一个模板类的对象,都可以直接通过显示实例化声明实例化类模板。
template class [类模板名]<实际类型列表>
// 如
template class ClassName<int>;
3.函数模板调用方式
3.1 隐式模板实参调用
在发生函数模板的调用时,不显示给出模板参数而经过参数推演,称之为函数模板的隐式模板实参调用(隐式调用)。
template <typename T> void func(T t) {
cout << t << endl;
}
func(5); //隐式模板实参调用
3.2 显示模板实参调用
在发生函数模板的调用时,显示给出模板参数而不需要经过参数推演,称之为函数模板的显示模板实参调用(显示调用)。
显示模板实参调用在参数推演不成功的情况下是有必要的。
#include <iostream>
using namespace std;
template <typename T> T Max(const T& t1, const T& t2) {
return (t1>t2)?t1:t2;
}
int main() {
int i=5;
//cout<<Max(i,'a')<<endl; // 无法通过编译
cout << Max<int>(i,'a') << endl; // 显示调用,通过编译
}
直接采用函数调用Max(i,'a')
会产生编译错误,因为 i 和 ‘a’ 具有不同的数据类型,无法从两个参数中选出一个作为函数模板的类型实参。而采用Max< int>(i,'a')
调用后,函数模板的实例化不需要经过参数推演,而函数的第二个实参也可以由 char 转换为 int 型,从而成功完成函数调用。
编码时建议采用显示模板实参的方式调用函数模板,这样提高了代码的可读性,便于代码的理解和维护。
参考文献
陈刚.C++高级进阶教程[M].武汉:武汉大学出版社,2008.P215-227