在前两节中(C++模板详解(一)、C++模板详解(二)),咱们了解了函数模板和类模板的基本概念和使用方法。在这篇博文里,咱们主要来详细地阐述一下"模板的参数声明"这个话题,而且也谈及了函数模板和类模板相结合的使用方式和一些注意事项。html
函数模板能够做为普通类和模板类的成员函数。下面的这份代码片断演示了这一点:函数
template<typename T1> class List { public: // 位于模板类中的成员函数模板定义: template<typename T2> List(const List<T2>& other); // 错误的写法:不能够是虚函数。 template<typename T1> virtual void func(T1&& t) { } }; // #1: 在类的外部定义上面的构造函数。 template<typename T1> template<typename T2> List<T1>::List(const List<T2>& other) { //... } class Collection { // 位于普通类内部的成员函数模板定义: template<typename T> T* alloc() { //... } // 错误的写法:不能够是虚函数。 template<typename T> virtual void func(T&& t) { } };
这份代码展现出了不少的概念。code
不管是普通类仍是模板类,其中的成员函数或是模板成员函数均可之内联地定义在类中,或是定义在类的外部。在外部定义的成员函数模板能够具备多个模板参数子句:一个子句做用于该模板自身,其它子句做用于外围的类模板,其顺序是从最外围的类模板开始,依次到达内部模板。htm
成员函数模板不能够是虚函数。这是由于,实现虚函数须要使用一个固定大小的虚函数表,每一个虚函数都对应虚函数表的一个入口。然而,成员函数模板的实例化个数,要等到整个程序都编译完成时才能肯定,这就和"虚函数表的大小是固定的"发生了冲突。因此,成员函数模板不能够是虚函数。blog
模板类的定义也是能够嵌套的。例以下面这份示例代码:get
// 示例1:模板类能够被嵌套定义在模板类中。 template<typename T1> class List { // 定义并实现。 template<typename T2> class Node1 { }; // 定义。 template<typename T2> class Node2; }; // 外部实现。 template<typename T1> template<typename T2> class List<T1>::Node2 { }; // 示例2:模板类能够被嵌套定义在普通类中 class Shell { // 定义并实现。 template<typename T> class Inner1 { }; // 定义。 template<typename T> class Inner2; }; // 外部实现。 template<typename T> class Shell::Inner2 { };
相似于成员函数的类外实现,内部类的具体实现也一样能够被放到类外进行,它们的书写规则和模板成员函数几乎相同。io
函数模板一样能够在声明中提供缺省参数:编译
template<typename T> void report(const Stack<T>& stack, int number = 10); template<typename T> void fill(const Array<T>& arr, const T& value = T());
因为和普通函数的缺省参数功能类似,具体的注意事项能够直接参看:C++函数详解。模板