概述
与函数模板相同,类模板也已关键字template
开头,后接模板参数以及类模板的声明或实现.模板参数在整个类实现中都可见,也就是可以在类实现中利用模板参数定义成员变量类型,成员函数参数类型及返回值类型等.
template<typename T>
struct ListNode
{
T value;
ListNode* next;//等价于ListNode<T>* next;
}
在上例中,模板参数 T 被用于定义成员变量 value 的类型,另一个成员变量 next 指向一个ListNode的指针,但ListNode只是一个模板名,并不代表实际的类.在此,c++有一个特别的规定:在一个类模板内出现的自身模板名,等价于该模板被调用时所生成的实例.
类模板参数也支持默认值,如果类模板参数有默认值,则在实参列表可中将其省略,如果所有参数都有默认值,则模板实参列表可以省略,但尖括号不可省略.
ListNode<> inode;
另外,与函数模板不同,类模板没有模板参数实参推导机制,所以,对于没有默认值的模板参数只能一一为其赋值,而可以省略的列表只限于列表最后有默认值的若干参数.
类模板不仅可以用来生成类的实例,还可作为其他类或模板类的基类.类模板的基类必须是某个类型,如下:
template<typename T>
class CountStack : public MyStack<T>
{};
如果是普通类以类模板实例为基类,需要为基类模板给定明确的模板参数值.
class CharStack : public MyStack<char>
{};
异质链表
上例的类模板ListNode中只有一个模板参数,即节点所保存的数据类型T,而节点的另一个成员变量next指针,其类型固定为指向另一同类型节点类,这就使得整个链表只能保存同一类型的数据.
若是next指针所指类型也由一个新的模板参数定义,则next可指向任何一种类型,那么由此节点类模板的一系列实例构成的链表就可用于保存不同类型的值,从而构成异质链表.
template<typename T, typename N>
struct HeteroNode
{
T value;
N* next;
HeteroNode(T const& v, N* n):value(v), next(n){};
};
int main(int argc, char* argv[])
{
typedef HeteroNode<int,void> node_0;
typedef HeteroNode<char,node_0> node_1;
typedef HeteroNode<std::string,node_1> node_2;
node_0* p0 = new HeteroNode<int,void>(12,nullptr);
node_1* p1 = new HeteroNode<char,node_0>('t',p0);
node_2* p2 = new HeteroNode<std::string,node_1>("lumin", p1);
std::cout << p2->value << " " << p2->next->value << " " << p2->next->next->value << " \n";
return 0;
}
原文首发于本人独立博客;转载注明出处