普通类的成员函数模板
不管是普通类还是类模板,它的成员函数可以是一个函数模板,称为“成员函数模板”,不可以是虚函数,否则编译器会报错。
class A{
public:
template<typename T>
void myfunc(T tmpt){
cout << tmpt << endl;
}
};
int main(){
A a;
a.myfunc(3); //函数模板,编译器会根据给定参数推断模板参数
}
类模板的成员函数模板
template <typename C>
class A{
public:
template<typename T2> //构造函数也引入自己的模板,和整个类的模板参数C没有关系
A(T2 v1, T2 v2){
cout << v1<< endl;
}
template<typename T>
void myfunc1(T tmpt){ //每个模板函数有自己的模板参数
cout << tmpt << endl;
}
template<typename T>
void myfunc2(T tmpt); //每个模板函数有自己的模板参数
};
template <typename C>
template <typename T>
void A<C>::myfunc2(T tmpt)
{
}
int main(){
A<float> a(1, 2); //此时 .obj 文件不会生成成员函数 myfunc1\myfunc2 的代码
a.myfunc1(2); //此时 .obj 文件才会生成成员函数 myfunc1的代码
}
类模板的成员函数(包括普通成员函数、成员函数模板)只有为程序所用时(代码中出现了)才会实例化。如果某函数从未使用则不会实例化(.obj 中生成代码)该成员函数。
(也就是说如果代码中没有调用到类成员函数时,编译器编译生成的 .obj 文件中是没有这个成员函数代码的)
模板显示实例化、模板声明
为了防止在多个.cpp 文件中都实例化相同的 类模板,所以C++11中提出了一个解决方法,我们称为是“显示实例化”。
通过显示实例化来避免这种生成多个相同类模板所带来的开销。
//A.h
template <typename C>
class A{
public:
template<typename T2> //构造函数也引入自己的模板,和整个类的模板参数C没有关系
A(T2 v1, T2 v2){
cout << v1<< endl;
}
template<typename T>
void myfunc1(T tmpt){ //每个模板函数有自己的模板参数
cout << tmpt << endl;
}
template<typename T>
void myfunc2(T tmpt); //每个模板函数有自己的模板参数
};
//file.cpp
#include "A.h"
template A<float>; //显示实例化手段中的“实例化定义”,编译器遇到这段代码则直接实例化出
//一个A<float>
int main(){
A a;
}
只需要在一个 .cpp 文件中做实例化定义,在其他 .cpp 文件中做实例化声明
extern template A<float>
extern作用:不会在本文件中生成一个 extern后边所表示的模板的实例化版本。
extern目的:高作编译器,在其他的源 .cpp文件 中已经有了一个该模板的实例化版本了。
(extern实际上可能没有达到我们预期系统所能达到的效果,还是会实例化类模板)
模板的实例化定义只有一个,实例化声明可以有多个。
总结:
vs2017不太推荐这个特色写法。