成员函数模板和模板显式实例化
1.成员函数模板
不论是一个普通的类,还是一个类模板,他成员函数本身可以是一个函数模板,这种成员函数称为“成员函数模板”,但是这种成员函数模板不可以是虚函数,如果是虚函数,则编译器报错
1.普通类的成员函数模板:
class A{
public:
template<typename T>
void myft(T tmpt)
{
cout << tmpt << endl;
}
}
2.类模板的成员函数模板
template<typename C>
class A
{
public:
template<typename T2>
A(T2 v1, T2 v2) //构造函数也引入自己的模板参数T2,和整个类的模板参数C没有关系
{
}
template<typename T>
void myft(T tmpt)
{
cout << tmpt << endl;
}
C m_ic;
};
如果想把成员函数模板的实现代码写到类模板定义外面,应该这样写
template<typename C>
class A
{
public:
template<typename T2>
A(T2 v1, T2 v2); //构造函数也引入自己的模板参数T2,和整个类的模板参数C没有关系
template<typename T>
void myft(T tmpt)
{
cout << tmpt << endl;
}
C m_ic;
};
template <typename C> // 先跟类模板的模板参数列表,要排在上面(如果排在下面会报错)
template <typename T2> // 再跟构造函数模板自己的模板参数列表
A<C>::A(T2 v1, T2 v2)
{
cout << v1 << v2 << endl;
}
2.模板显式实例化与声明
前面已经说过模板只有被使用时才会被实例化
就是上面的A类模板,如果放在一个h文件中,有两个cpp同时调用这个h文件,并且都实例化的话,其实是会实例化两个出来的,如果项目很大,有多个cpp,则会实例化很多相同的类模板,开销也很大,增大了编译的时间
可以通过显式实例化来避免这种生成多个相同类模板实例的开销
可以在第一个cpp文件头写上
template A<float> //这叫实例化定义,只有一个cpp文件这样写,编译器为其生成代码
其他cpp的头上声明这个实例化出来的类就行了
extern template A<float> //其他的cpp都这样写
在头上写,是因为编译器遇到这些使用类模板的代码会自动会对模板实例化,所以在cpp头上写的代码肯定比那些使用该类模板的代码先执行到
带extern的代码行,成为模板实例化声明,extern的意思就是告诉编译器,其他的cpp已经有一个类的实例化版本了
template A是类的实例化定义
extern template A是类的实例化声明
只有一个定义,但是可以有多个声明
但是一旦用template A 进行显式实例化的话,系统会把这个类模板以及所有成员函数都给实例化出来(感觉这样并不好),包括内联的成员函数,同时如果代码中调用了哪个函数模板,那么系统也会把这个函数模板根据所调用的参数实例化出来
使用VS17和19的话,不推荐使用类模板显式实例化特色,因为虽然有作用,但是也会把所有成员都实例化出来,增加编译时间和代码长度
- 点赞
- 收藏
- 关注作者
评论(0)