template
1.定义模板时用template
2.template<typename T1,typename T2,....typename Tn>,尖括号里的参数可有有多个,即多个类型,用逗号隔开。
3.在使用模板的每个块都要加上模板声明。
4.在调用模板函数时,编译器自动生成多个重载函数。
例1. 简单函数
template<typename T>
bool equal(const T & a, const T & b)
{
return a == b;
}
bool equal(const int a, const int b)
{
return a == b;
}在同时定义了模板函数和非模板函数,在调用时优先调用非模板的函数
例2. 顺序表
template<typename T>
class SeqList
{
public:
SeqList( int capacity =7)
:_data( NULL)
, _size(0)
, _capacity( capacity)
{
_data = new T [_capacity];
}
~SeqList()
{
if (_data != NULL )
delete[]_data;
}
public:
void CheckCapacity()
{
if (_size == _capacity)
{
T*tmp = new T[_capacity + 7];
memcpy(tmp, _data, _size*sizeof(T ));
delete[] _data;
_data = tmp;
_capacity = _capacity + 7;
}
}
public:
void PushBack(const T&d);
void PushFront(const T&d);
void PopBack();
void PopFront();
void Print()
{
int i = 0;
for (i = 0; i < _size; i++)
{
cout << _data[i] << " " ;
}
cout <<"over" << endl;
}
private:
T* _data;
T _size;
T _capacity;
};
template<typename T>
void SeqList <T>::PushBack( const T &d)
{
CheckCapacity();
_data[_size] = d;
_size++;
}
template<typename T>
void SeqList <T>::PushFront( const T &d)
{
CheckCapacity();
T start = _size-1;
while (start >= 0)
{
_data[start+1] = _data[start];
start--;
}
_data[0] = d;
_size++;
}
template<typename T>
void SeqList <T>::PopBack()
{
_size--;
}
template<typename T>
void SeqList <T>::PopFront()
{
T start = 0;
_data[0] = NULL;
for (start = 0; start < _size; start++)
{
_data[start] = _data[start + 1];
}
_size--;
}在main函数中使用模板时,指定模板中T的类型
int main()
{
SeqList<int >S1;
S1.PushBack(1);
S1.PushBack(3);
S1.PopBack();
S1.Print();
S1.PushFront(5);
S1.PopFront();
S1.Print();
getchar();
return 0;
}例3. 双向链表
template<typename T>
struct Node
{
Node( const T &d)
:next(NULL)
, prev(NULL)
, _data(d)
{
}
T _data;
Node<T>* next;
Node<T>* prev;
};
template<typename T>
class Dlist
{
public:
Dlist();
~Dlist();
Dlist( const Dlist& d);
Dlist & operator=(const Dlist&d);
public:
void PushFront(T const & d);
void PopFront();
void PushBack(T const & d);
void PopBack();
void Print();
void Reverse();
private:
Node<T>*_head;
Node<T>*_tail;
};
template<typename T>
Dlist<T>::Dlist()
:_head(NULL)
,_tail(NULL)
{}
template<typename T>
Dlist<T>::~Dlist()
{
Node<T>*cur = _head;
while (cur)
{
Node<T>*del = cur;
cur = cur->next;
delete del;
}
}
template<typename T>
Dlist<T>::Dlist(const Dlist& d)
:_head(NULL)
, _tail(NULL)
{
Node<T>* cur = d._head;
while (cur)
{
PushBack(cur->_data);
cur = cur->next;
}
}
template<typename T>
void Dlist<T>::PushFront(T const & d)
{
Node<T>*newNode = new Node<T>(d);
if (_head == NULL)
{
_head = newNode;
_tail = newNode;
}
else
{
newNode->next = _head;
_head->prev = newNode;
_head = newNode;
}
}
template<typename T>
void Dlist<T>::PopFront()
{
if (_head == NULL)
return;
if (_head == _tail)
{
delete _head;
_head = NULL;
_tail = NULL;
return;
}
Node<T>*del=_head;
_head = _head->next;
_head->prev = NULL;
delete del;
}
template<typename T>
void Dlist<T>::PushBack(T const & d)
{
Node<T>*newNode = new Node<T>(d);
if (_head == NULL)
{
_head = newNode;
_tail = newNode;
}
_tail->next = newNode;
newNode->prev = _tail;
_tail = newNode;
}
template<typename T>
void Dlist<T>::PopBack()
{
if (_head == NULL)
return;
if (_tail == _head)
{
delete _head;
_tail = NULL;
_head = NULL;
}
_tail = _tail->prev;
delete _tail->next;
_tail->next = NULL;
}
template<typename T>
void Dlist<T>::Print()
{
Node<T>*cur = _head;
while (cur != NULL)
{
cout << cur->_data << "->";
cur = cur->next;
}
cout << "over"<< endl;
}
template<typename T>
void Dlist<T>::Reverse()
{
if ((_head == _tail) || (_head == NULL))
return;
Node<T>*cur = _head;
while (cur->next)
{
swap(cur->next, cur->prev);
cur = cur->prev;
}
swap(_head, _tail);
}类模板特化
1.全特化
在基于模板template<typename T>的版本上,重写其中某个特定的类型,在main中若调用了这个函数时,若是重写的这个特定类型,就调用重写的特定类型函数,而不调用模板函数。
2.偏特化/部分特化
(1). 特化其中一个
template<typename T1,typename T2> //..... template<typename T1> class Date<T1 ,int>
(2).特化两个参数为指针类型等
class Date<T1*,T2*>
模板的分离编译
在以往的程序编写中,把宏和函数声明放入头文件(*.h),函数定义放到(*.cpp)文件,函数的main函数等测试函数放到(test.cpp)中。但是模板函数不能分离编译,由于每个文件都是单独编译的,在创建类的文件中没有创建对象实例化,在测试的模板文件中没有类的声明,导致编译失败。
解决方案:把声明和定义均放到同一个文件中(*.hpp)。
友元operator函数在写成模板时只能放到类内实现
template <typename T>
class Date
{
template<typename Type>
friend ostream operator<<(ostream& os, const Data<Type>& d)
{
os << d ._d << endl;
return os ;
}
public:
//...
private:
T _d;
//...
};本文出自 “无以伦比的暖阳” 博客,请务必保留此出处http://10797127.blog.51cto.com/10787127/1755480
原文:http://10797127.blog.51cto.com/10787127/1755480