前文回顾:
C++ 泛型编程(一) 基本概念
C++ 泛型编程(二) 函数模版
C++ 泛型编程(三) 模版实参推断
类模版
-
定义
①.定义
类模版是用来生成类的蓝图的。类似函数模版的定义,类模板以关键字 template 开始,后跟尖括号包围的模版参数列表,用关键字 typename 来定义模版参数类型。
template <typename T> class A { A();// };
②.类模版实例化
不同于函数模版,编译器无法为类模版推断实参类型,使用时必须显式指定模版类型。一个类模版的每一个实例都是一个独立的类,互相之间没有任何关系。
template <typename T> class A { A();// }; A<int> a1; A<string> a2;
-
成员函数
①.成员函数定义
类模版的每个实例都有自己版本的成员函数,因此类模版的成员函数具有和模板相同的模版参数;在类外定义成员函数必须以 template 开始。
template <typename T> class A { A();// void f1(string & s)//类内定义成员函数 { cout << s << endl; } void f2( int i); }; //类外定义成员函数 template <typename T>//模版声明 void A<t>::f2( int i)//指明类型作用域 { cout << i << endl; }
②.类模板头文件
为了生成一个实例化版本,编译器需要掌握类模版成员函数的定义,因此类模版以及其成员函数都必须在头文件中进行定义。
③.成员函数实例化
对于一个实例化了的类,其成员函数只有在程序用到它时才会被实例化。
string temp = "hello"; A<int> a1;//类实例化 a1.f1(s);//实例化一个成员函数
-
类模版与友元
当一个类包含一个友元声明时,类与友元各种是否是模版是互相无关的。如果一个类模版包含一个非模版友元,则友元可以访问所有类模版实例;如果友元自身是模版,类可以授权给所有友元模版实例,也可以只授权给特定实例。
-
默认模版实参
同函数模版可以定义默认模版实参,类模版也可以为模版参数提供默认实参。类模版的默认实参需要遵循从右向左的规则进行指定。当希望使用默认实参时,在模版名后加空尖括号对即可。
template <typename T1,typename T2 = int> // T2 默认为 int class P { public: P(T1 m_name, T2 m_age) :name(m_name), age(m_age) {}; private: T1 name; T2 age; }; P<string> p("张三", 12);// T2 使用默认实参
-
成员模版
一个类可以包含本身是模版的成员函数,这种函数称为成员模版;类本身可以是普通的类,也可以是类模版;成员模版不能是虚函数。
-
显式实例化类模版
同模版函数的显示实例化定义,类也可以用 extern 来声明一个外部的模版定义,即承诺在其他位置有该实例的一个定义;类模版的实例化定义会实例化类的所有成员。
extern template class P<string,int>;//承诺在其他位置进行了实例化定义 P<string,int>("张三",12); #include "test.h" //必须为其他位置声明为 extern 的类型提供一个非 extern 定义 template class P<string,int>;//实例化定义