一、定义函数模板
template<class T>
函数定义
举个例子比较两个数大小:
template<class T> int Compare(T a,T b) { if(a>b)return ; if(a<b)return -; return ; } int main()
{
int a=;
int b=;
char c='w';
char d='w';
double e=3.1415;
double f=2.123;
cout<<Compare(a,b)<<endl;
cout<<Compare(c,d)<<endl;
cout<<Compare(e,f)<<endl;
return ;
}
二、定义类模板
template<参数列表>
类定义
1、在定义类模板之前要先说明一个问题,因为这几天把C++中头文件的声明和定义学习了一下。刚好碰到类模板的学习,因此就此小试牛刀。但是这一试让我郁闷呢了好长时间,因为我还是和往常一样把类的声明放在一个*.h的头文件中,具体实现放在*.cpp文件中。但是让我很很很是郁闷的是,构造函数老是编译不能通过老是出现下面这个错误:
error LNK2001: unresolved external symbol "public: __thiscall LinkList<char>::LinkList<char>(void)" (??0?$LinkList@D@@QAE@XZ)
Debug/TemplateLinkList.exe : fatal error LNK1120: 1 unresolved externals
我勒个擦,我最怕这种东西,查阅了好多资料一直没发现是哪有问题,最后终于在今天在网上看到了这篇博文才知道自己C++真是太水了:(http://www.cnblogs.com/tonyyang132/archive/2009/11/12/1601868.html和http://bbs.csdn.net/topics/70471835)
按照C++中代码的惯例,类声明在h文件中,类定义在cpp文件中,相应的成员函数声明也在h文件中,定义在cpp文件中。但是如果这样的架构用在模板函数中,在调用模板函数的地方链接器便会报错,error LNK2001: unresolved external symbol。将定义写在与声明相同的文件中问题解决,解释如下:
“大部分编译器在编译模板时都使用包含模式。也就是一般使用的把模板放到头文件中再包含。
当你不使用这个模版函数或模版类,编译器并不实例化它。当你使用时,编译器需要实例化它。因为编译器是一次只能处理一个编译单元,也就是一次处理一个cpp文件,所以实例化时需要看到该模板的完整定义,所以都放在头文件中。
这不同于普通的函数,在使用普通的函数时,编译时只需看到该函数的声明即可编译,而在链接时由链接器来确定该函数的实体。”
2、在写类模板之前还要注意一点,在类模板作用域内,可以用他的非限定名字引用该类。比如:
#ifndef NODE_H_H
#define NODE_H_H
template<class T>class LinkList;
template<class T>
class Node
{
friend LinkList<T>;
private:
T Data;
Node *Next;//完整为Node<T> *Next;
};
#endif
此处的Node<T> *Next可以写为Node *Next,但是为了保证不出错无论在不在类模板的作用域内都用它的限定名引用该类。还有注意一点假设有一个成员函数返回的是指向该模板类的指针,返回类型也必须为该模板的限定名引用该类。
template <class T>
Node<T> *LinkList<T>::Create(int len)//注意这里的返回值为类模板类型Node<T>
{
Node<T> *p;
Node<T> *temp;
T s;
while(len--)
{
cout<<"输入数据:"<<endl;
cin>>s;
temp=new Node<T>;
temp->Data=s;
temp->Next=NULL;
if (!head)
{
head=temp;
p=head;
}
else
{
p->Next=temp;
p=temp;
}
}
return head;
}
3、因为这里是用类写而且class Node{};成员为私有,因此在class LinkList{};使用Node类的数据成员要在class Node{};声明为friend。
4、贴出完整代码和运行结果。
//Node.h
#ifndef NODE_H_H
#define NODE_H_H
template<class T>class LinkList;
template<class T>
class Node
{
friend LinkList<T>;
private:
T Data;
Node *Next;
};
#endif
/*-------------------------------------------*/
//LinkList.h
#include "Node.h"
#ifndef LINKLIST_H_H
#define LINKLIST_H_H
template<class T>
class LinkList
{
private:
Node<T> *head;
public:
LinkList();
~LinkList();
void Insert(T data);
void printLinkList();
Node<T> *Create(int len);
};
#endif template<class T>
LinkList<T>::LinkList()
{
head=NULL;
} template<class T>
LinkList<T>::~LinkList()
{
Node<T> *p;
while(head)
{
p=head->Next;
delete head;
head=p;
cout<<"析构!"<<endl;
}
}
template <class T>
Node<T> *LinkList<T>::Create(int len)
{
Node<T> *p;
Node<T> *temp;
T s;
while(len--)
{
cout<<"输入数据:"<<endl;
cin>>s;
temp=new Node<T>;
temp->Data=s;
temp->Next=NULL;
if (!head)
{
head=temp;
p=head;
}
else
{
p->Next=temp;
p=temp;
}
}
return head;
}
template<class T>
void LinkList<T>::Insert(T data)
{
Node<T> *p=head;
Node<T> *s=new Node<T>;
s->Data=data;
s->Next=NULL;
if (head==NULL)
{
head=s; }
else
{
while(p->Next)
{
p=p->Next;
}
p->Next=s;
}
} template<class T>
void LinkList<T>::printLinkList()
{
Node<T> *p=head;
while(p)
{
cout<<p->Data<<endl;
p=p->Next; }
}
/*--------------------------------------------------------------------*/
//TemplateLinkList.cpp
#include <iostream>
#include<string>
#include "Node.h"
#include "LinkList.h"
using namespace std; int main()
{
LinkList<char> L;
L.Insert('a');
L.Insert('b');
L.Insert('c');
L.printLinkList(); LinkList<string> s;
s.Insert("abcd");
s.Insert("efgh");
s.Insert("ijkl");
s.printLinkList(); LinkList<int> t;
t.Insert();
t.Insert();
t.Insert();
t.printLinkList(); LinkList<double> d;
Node<double> *b;
b=d.Create();
d.printLinkList(); //Node<int> n;
return ;
}