概述
與函數模板相同,類模板也已關鍵字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;
}
原文首發于本人獨立博客;轉載注明出處