类模板的格式为
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");
}
模板类的成员函数不一定是模板函数,因此除了类模板的特例化还可以对成员函数模板实现特例化。在类中的普通成员函数、模板成员函数、特例化函数中优先调用普通成员函数、特例化成员函数然后是模板成员函数,精确匹配时按顺序对比,若未找到时生成模板成员函数。