1. 关于类模板的成员函数
在类外定义的类模板的成员函数具有如下形式:
[1] 必须以关键字 template 开头,后接类的模板形参表
[2] 必须指出它是哪个类的成员
[3] 类名必须包含其模板形参
2. 成员模板 (member template)
任意类(模板或非模板)可以拥有本身为类模板或函数模板的成员,这种成员称为成员模板。成员模板不能为虚。
[1] nested class templates
[2] member function templates
当在类模板作用域外部定义成员模板的时候,必须包含两个模板形参表。
补充:
嵌套类(nested class)是独立的类,基本上与它的外围类不相关。因此,外围类和嵌套类的对象是相互独立的。嵌套类型的对象不具备外围类所定义的成员,同样,外围类的成员也不具备嵌套类所定义的成员。
下面是关于成员函数模板的一个例子.
考虑两个Stack相互赋值,也就是将其中一个整体赋值给另一个。
你不能把某种类型的 Stack赋值给另一种类型的Stack,即使这两种类型之间可以隐式转型:
Stack<int> intStack1, intStack2;
Stack<float> floatStack;
...
intStack1 = intStack2; // OK
floatStack = intStack1; // ERROR
只要把 assignment 运算符定义为一个 template,你就可以让两个「类型不同,但其元素可隐式转型」的 stacks 互相赋值。
#include <deque>
#include <stdexcept>
using namespace std;
template<typename T>
class Stack{
private:
deque<T> elems;
public:
void push(const T& x){ elems.push_back(x); }
void pop(){
if (empty())
throw out_of_range("Statk<>::pop():empty stack");
elems.pop_back();
}
T top() const {
if (empty())
throw out_of_range("Statk<>::top(): empty stack");
return elems.back();
}
int size()const { return elems.size(); }
bool empty() const {
return elems.empty();
}
//member function template
//在拥有 template parameter T 的模板中定义一个内层的(inner)template parameter T2
template<typename T2>
Stack<T> & operator=(const Stack<T2>& rhs);
};
template<typename T>
template<typename T2>
Stack<T>& Stack<T>::operator=(const Stack<T2>& rhs){
if ((void*)this == (void*)&rhs) // 判断是否赋值给自己
return *this;
Stack<T2> temp(rhs); //会有构造开销
elems.clear();
while (!temp.empty()){
elems.push_front(temp.top());
temp.pop();
}
return *this;
}