類模板的格式爲
template <class T>
class List;
template<typename T>//typename和class 可以互換
class Node
{
friend class List<T>;
/*
//不安全:對所有的模板類都友元
template <typename T>
friend class<T>List;
*/
public:
Node(T data = T(0))//0初始化
{
val = data;
next = NULL;
};
~Node()
{
}
private:
T val;
Node<T>* next;
};
template <class T>
class List
{
public :
List()
{
phead = new Node<T>();
}
void InsertHead(T data)
{
Node<T>* p = new Node<T>(data);
p->next = phead->next;
phead->next = p;
}
void Show();
~List()
{
Node<T>* pcur = phead;
Node<T>* pnext = phead;
while(pcur != NULL)
{
pnext = pcur->next;
delete pcur;
pcur = pnext;
}
phead = NULL;
}
private:
Node<T>* phead;
};
模板類中友元函數需要注意友元關係是一對一還是一對多,並且模板類外實現函數,也需要加上作用域。
template <class T>
void List<T>::Show()
{
Node<T>* pcur = phead->next;
while(pcur != NULL)
{
cout << pcur->val << " " ;
pcur = pcur->next;
}
cout <<endl;
}
代理的類間關係需要加上 typename關鍵字,舉個例子:
template <typename T>
class List
{
public:
List(T data = T(0))
{
head = new Node<T>(data);
}
class Node;//類聲明
private:
class Node
{
public:
Node* Find(T val);
T val;
};
Node head;
};
template <typename T>
typename List<T>::Node* List<T>::Node::Find(T val)//類名?靜態成員變量 編譯器傻傻分不清
{
return NULL;
}
非模板類中也是可以有模板成員函數。
class Node
{
public:
Node(int data = 0)
{
cout <<"模板構造"<<endl;
};
template <typename T>
void fun(T a)
{
cout<<"普通類下的模板成員函數"<<endl;
}
private:
int val;
Node* next;
};
值得注意的一點是,模板類的拷貝構造函數是無效的,即使默認的拷貝構造沒用重載。
類模板特例化
template <typename T>
class List<T*>
{
//成員函數
}
特例化分爲部分特例化和完全特例化,完全特例化是對一種類型進行特例化,而部分特例化是對一些類似的數據類型進行處理,比如指針類型。
class Node
{
public:
void Show(char*)
{
cout <<"void Show" <<endl;
}
template <typename T>
void Show(T)
{
cout << "template<typename T>" << endl;
}
template <>
void Show(const char*)
{
cout << "template<>" <<endl;
}
private:
int data;
};
int main()
{
Node n1;
const int a = 10;
char *s = "abd";
n1.Show("1");
}
模板類的成員函數不一定是模板函數,因此除了類模板的特例化還可以對成員函數模板實現特例化。在類中的普通成員函數、模板成員函數、特例化函數中優先調用普通成員函數、特例化成員函數然後是模板成員函數,精確匹配時按順序對比,若未找到時生成模板成員函數。