1 類模板1.1 類模板的聲明
類模板的定義和實現都被放在標頭檔中,這點和函數模板類似。
Template<typename T>
Class Stack{
Private:
Std::vector<T> elems;
Public:
Stack();
Void push(T const&);
Void pop();
…
};
這個類的類型是Stack<T>,其中T是模板參數。所以,如果你要聲明自己實現的拷貝建構函式和賦值運算子,那麼應該這樣寫:
Template<typename T>
Class Stack{
Public:
Stack(Stack<T> const&);
Stack<T>& operator=(stack<T> const&);
…
};
當然,使用類名而不是類的類型時,就應該只使用stack,譬如,當你指定類的名稱、類的建構函式、解構函式,就應該用Stack;
1.2 成員函數的實現
為了定義類模板的成員函數,你必須指定該成員函數是一個函數模板,而其你還需要使用這個類模板完整類型限定符。因此,類型Stack<T>的成員函數push()的實現如下。
Template<typename T>
Void Stack<T>::push(T const& elem)
{
Elems.push_back (elem);
}
對於類模板的任何成員函數,你都可以把它實現為內嵌函式,將它實現於類的聲明裡面。
1.3 類模板的使用
為了使用類模板,你必須顯示的指定模板實參,類模板不會進行實參演繹,這點和函數模板有所不同。
只有那些被調用的成員函數,才會產生這些函數的執行個體化代碼。對於類模板,成員函數只有在被使用的時候才會被執行個體化。顯然,這樣可以節省空間的和時間;另一個好處是對於那些“未能提供所有成員函數中所有操作”的類型,你也可以使用該類型來執行個體化類模板,只要對那些“未能提供某些操作的”成員函數,模板內部不使用就可以了。
如果類模板中含有靜態成員,那麼用來執行個體化的每種類型,都會執行個體化這個靜態成員。
如果用類模板來作為模板參數時,要注意角括弧的位置。
Stack<stack<int> > intStackStack;
1.4 類模板的特化
和函數模板的重載類似,通過特化類模板,你可以最佳化基於某種特定類型的實現,或者克服某種特定類型在執行個體化類模板時所出現的不足。另外,如果要特化一個類模板,你還要特化該類模板的所有成員函數,雖然也可以只特化某個成員函數,但這個做法並沒有特化整個類,也就沒有特化整個類模板。
特化的文法:
Template<>
Class Stack<std::string>{
…
};
在進行類模板的特化時,每個成員函數都必須重新定義為普通函數,原來模板函數中的每個T也相應的被進行特化的類型取代。
如:
Void Stack<std::string>::push (std::string const& elem)
{
Elems.push_back(elem);
}
注意到,在函數定義的前面,沒有template<std::string>。
特化的實現可以和基本類模板的實現完全不同。
1.5 局部特化
類模板可以被局部特化,你可以在特定的環境下指定類模板的特定實現,並且要求某些模板參數仍然必須有使用者來定義。
如:
Template<typename T1, typename T2>
Class MyClass{…};
可以被特化為:
Template<typename T, typename T>
Class MyClass<T, T>{…};
Template<typename T>
Class MyClass<T, int>{…};
Template<typename T1, typename T2>
Class MyClass<T1*, T2*>{…};
1.6 預設模板實參
和函數模板不同,類模板的實參允許有預設值。
比如對於上面定義的Stack,就可以有下面的實現。
Template<typename T, typename CONT= std::vector<T> >
Class Stack{
…
};