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);
}


模板参数实现容量适配器

template<typename T>
class SeqList
{
public:
                SeqList( int capacity = 7)
                                :_size(0)
                                , _capacity( capacity)
                                , _data( NULL)
                {
                                _data = new T [_capacity];
                }
                ~SeqList()
                {
                                 if (_data != NULL )
                                {
                                                 delete[]_data;
                                }
                }
                 void PushBack(const T&d);
                 void PopBack();
                 void CheckCapacity()
                {
                                 if (_size == _capacity)
                                {
                                                 T *tmp = new T[_capacity + 7];
                                                memcpy(tmp, _data, _size*sizeof(T ));
                                                 delete[]_data;
                                                _data = tmp;
                                                _capacity = _capacity + 7;
                                }
                }
                
                 void Print()
                {
                                 int i = 0;
                                 while (i < _size)
                                {
                                                cout << _data[i] << " " ;
                                                i++;
                                }
                                cout << "over"<< endl;
                }
                
private:
                 int _size;
                 int _capacity;
                 T*_data;
                
};
template<typename T>
void SeqList <T>::PushBack( const T &d)
{
                CheckCapacity();
                _data[_size] = d;
                _size++;
}
template<typename T>
void SeqList <T>::PopBack()
{
                _size--;
}
template<typename T, template< class> class Container = SeqList >
class Stack
{
public:
                 void Push(const T&d)
                {
                                  _con.PushBack( d);
                }
                 void  Pop()
                {
                                _con.PopBack();
                }
                 void PrintStack()
                {
                                _con.Print();
                }
private:
                 Container<T > _con;
};
int main()
{
                 Stack<int ,SeqList>S1;
                S1.Push(1);
                S1.Push(2);
                S1.Push(3);
                S1.PrintStack();
                S1.Pop();
                S1.PrintStack();

                getchar();
                 return 0;
}


类模板特化

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;
                 //...
};