模板<template>
本篇博客阐述主要内容有:
1.模板的定义
2.模板函数
3.模板类
4.C++容器
-----------------------------------------------------
模板:望文生义,就是一个模子,在C++中提供重用源代码的方法;
函数的重载,就是解决函数接收不同类型的参数的问题而产生的,但是,我们往往是不愿意这样做的,因为这样的话,等于多写了一份代码,拉长了代码长度,于是,就有了模板的存在,模板只需要你写一份代码就可以实现不同类型数据的复;模板的一般使用方式是: template<class T,...>或者template<typename T,...> 尖括号里的模板参数;
例如下面这个简单的例子<函数模板>:
#include<iostream>
#include<string>
using namespace std;
template<typename T>
bool Equal(const T& a,const T& b)
{
return a==b;
}
int main()
{
cout<<Equal<int>(1,2)<<endl;//注意使用的方式,<传参类型>
cout<<Equal<int>(1.1,2)<<endl; //错误! 注意模板参数的匹配
cout<<Equal<string>("aaaaa","aaaaa")<<endl;//不同类型的参数
system("pause");
return 0;
}
这样就实现了不同类型参数的函数调用,那么,模板函数实现的机制是什么呢?
其实,这些事情都是编译器在默默的帮你完成.
模板类
我们知道类的实现也依赖于类成员的基本类型,那么模板是怎样实现类的呢?
举个简单例子:
#include<iostream>
using namespace std;
template<class T = int>// class 或者 typename 是一样的,类的模板参数可以有默认参数;
class Seqlist
{
T _data;
int _size;
int _capacity;
public:
Seqlist (const T& data,const int size,const int capacity)
:_data(data)
,_size(size)
,_capacity(capacity );
{}
};
写过顺序表的同学都知道,顺序表中的数据类型我们一般写的都是int,或者宏定义一下数据类型,为了方便以后数
据类型的修改,但是其实还是很麻烦的,而我再上面简单的用模板参数实现了顺序表数据成员的定义,这样后面所有
的类型都是T类型的;这样,同学们也可以试着用模板参数实现顺序表和链表;
模板的能力远不止这样,以后我会写关于类型萃取<模板的特化>的博客也是用的模板,还有已经写过的智能指针中
也用了模板!
《浅析智能指针一》
《浅析智能指针二》
在C++中有容器这样一个概念,比如我们所知道的栈和队列,我在下面贴出模板参数实现栈和队列的模拟实现:
-------------------------------------------------------------------------------------
模板参数实现栈
#include<iostream>
#include<string>
#include<cassert>
using namespace std;
template<class T>
class SeqList
{
public:
SeqList ()
:_pdata(NULL)
,_size(0)
,_capacity(3)
{
_pdata = new T[3];
}
~SeqList ()
{
if(_pdata != NULL)
{
delete[] _pdata;
_size = 0;
_capacity = 0;
}
}
void Display()
{
for(int i = 0; i<_size; i++)
{
cout<<_pdata[i]<<" ";
}
cout<<endl;
}
void PushBack(const T& data);
void PushFront(const T& data);
void PopBack();
void PopFront();
void Sort();
int Find(const T& P);
void Intsert(const int& pos,const T& data);
void Remove(const T& data);
void RemoveAll(const T& data);
T& operator[](int size)
{
assert(size<_size);
assert(size>=0);
return _pdata[size];
}
public:
void CheckCapacity()
{
int NewCapacity = _capacity*2 + 3;
if(_size == _capacity)
{
T* tmp = new T[NewCapacity];
for(int i = 0; i<_size; i++)
{
tmp[i] = _pdata[i];
}
delete[] _pdata;
_pdata = tmp;
_capacity = NewCapacity ;
}
}
T* _pdata;
int _size;
int _capacity;
};
template<typename T>
int SeqList <T>::Find(const T& data)
{
int i = 0;
for(i= 0 ; i < _sz; i++)
{
if(_pdata[i] == data)//注意这里的等号,千万别写成赋值等;
return i;
}
return -1;
}
template<typename T>
void SeqList<T>:: PushBack(const T& data)
{
CheckCapacity ();
_pdata[_size] = data;
_size++;
}
template<class T>
void SeqList<T>::PushFront(const T& data)
{
CheckCapacity();
int length = _size;
while(length)
{
_pdata[length]=_pdata[length-1];
length--;
}
_pdata[0] = data;
_size++;
}
template<typename T>
void SeqList <T>::PopBack ()
{
if(_size>=1)
{
_size-=1;
}
}
template<typename T>
void SeqList <T>::PopFront()
{
int len = 0;
while(len<_size-1)
{
_pdata[len] = _pdata[len+1];
len++;
}
_size--;
}
template<typename T>
void SeqList <T>::Intsert(const int& pos, const T& data)
{
CheckCapacity ();
int index = Find(pos);
if(index>=0)
{
int length = _size;
while(length > index)
{
_pdata[length]=_pdata[length-1];
length--;
}
_pdata[index] = data;
_size++;
}
}
template<typename T>
void SeqList <T>::Remove(const T& data)
{
int index = Find(data);
if(index>=0)
{
while(index<_size-1)
{
_pdata[index] = _pdata[index+1];
index++;
}
}
_size--;
}
template<typename T>
void SeqList <T>::RemoveAll (const T& data)
{
while(Find(data)>=0)
{
Remove(data);
}
}
template<typename T>
void SeqList <T>::Sort ()
{
for(int i = 0; i<_size-1; i++)
{
for(int j = 0; j < _size-i-1; j++)
{
if(_pdata[j]<_pdata[j+1])
{
T tmp = _pdata [j];
_pdata [j] = _pdata [j+1];
_pdata [j+1] = tmp;
}
}
}
}
template<typename T, typename Container>
class Stack
{
public:
void Push(const T& data)
{
_con.PushBack(data);
}
T& Top()
{
int sz = _con._size - 1;
return _con._pdata[sz];
}
bool Empty()
{
return _con._size == 0;
}
void Pop()
{
_con.PopBack();
}
void Display()
{
while(!Empty())
{
cout<<Top()<<" ";
Pop();
}
}
private:
Container _con;
};
void test()
{
SeqList<string> s;
SeqList<int> s1;
s1.PushBack(2);
s1.PushBack(5);
s1.PushBack(4);
s1.PushBack(6);
s.PushBack ("aaaaaaaaaaaaaa");
s.PushBack ("dsadsas");
s.PushBack ("ssssssssssss");
s.PushBack ("sdasadadafffffffffffffffffffffffffffffffffff");
s.PushBack ("sdasdas");
s1.Sort ();
s1.Display ();
}
void test1()
{
Stack<int , SeqList<int>> s;
s.Push (1);
s.Push (1);
s.Push (3);
s.Push (4);
s.Push (2);
s.Display ();
}
int main()
{
test1();
system("pause");
return 0;
}
-----------------------------------------------------------------------------------------------------
模板参数实现队列
// 模板参数模拟实现队列
#include<iostream>
using namespace std;
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 LinkList
{
public:
LinkList ()
:_head(NULL)
,_tail(NULL)
{}
~LinkList ()
{
Node<T>* cur =_head;
while(cur)
{
Node<T>* tmp = cur;
cur = cur->_next ;
delete tmp;
}
_head = _tail = NULL;
}
void PushBack(const T& data);
void PushFront(const T& data);
void PopBack();
void PopFront();
void Remove(const T& data);
void RemoveAll(const T& data);
void Sort();
void Display();
Node<T>* GetHead()
{
return _head;
}
private:
Node<T>* _head;
Node<T>* _tail;
};
template<typename T>
void LinkList<T>::PushBack(const T& data)
{
Node<T>* pNode = new Node<T>(data);
if(_head==NULL)
{
_head = _tail = pNode;
}
else
{
_tail->_next = pNode;
pNode->_prev = _tail;
_tail = pNode ;
}
}
template<typename T>
void LinkList <T>::PushFront(const T& data)
{
Node<T>* pNode = new Node<T>(data);
if(_head==NULL)
{
_head = _tail = pNode;
}
else
{
pNode->_next = _head;
_head->_prev = pNode;
_head = pNode;
}
}
template<typename T>
void LinkList <T>::PopBack ()
{
if(_head==NULL)
return;
else if(_head->_next == NULL)
{
delete _head;
_head = _tail = NULL;
}
else
{
Node<T>* tmp = _tail;
_tail = _tail->_prev ;
_tail->_next = NULL;
delete tmp;
}
}
template<typename T>
void LinkList <T>::PopFront ()
{
if(_head==NULL)
return;
Node<T>* tmp = _head;
_head->_prev = NULL;
_head = _head->_next ;
delete tmp;
}
template<typename T>
void LinkList <T>::Remove (const T& data)
{
Node<T>* cur = _head;
while(cur)
{
if(cur->_data == data)
{
if(cur->_prev == NULL)
{
PopFront ();
}
else if(cur->_next == NULL)
{
PopBack ();
}
else
{
Node<T>* t = cur;
cur->_next ->_prev = cur->_prev ;
cur->_prev ->_next = cur->_next ;
delete t;
}
return;
}
cur = cur->_next ;
}
}
template<typename T>
void LinkList<T>::RemoveAll (const T& data)
{
Node<T>* cur = _head;
while(cur)
{
if(cur->_data == data)
{
if(cur == _head)
{
cur = cur->_next ;
PopFront ();
}
else if(cur->_next == NULL)
{
PopBack ();
cur = NULL;
break;
}
else
{
/*Node<T>* t = cur->_next;
cur->_next ->_prev = cur->_prev ;
cur->_prev ->_next = cur->_next ;
delete cur;
cur = t;*/
cur->_data = _tail->_data ;
PopBack();
}
}
else
cur = cur->_next ;
}
}
template<typename T>
void LinkList <T>::Sort ()
{
//链表的冒泡排序;
Node<T>* cur = NULL;
Node<T>* teil = NULL;
cur = _head ;
while(cur != teil)
{
while(cur->_next != teil)
{
if(cur->_data > cur->_next ->_data )
{
T tmp = cur->_data ;
cur->_data = cur->_next ->_data ;
cur->_next ->_data = tmp;
}
cur = cur->_next ;
}
teil = cur;
cur = _head;
}
return ;
}
template<typename T>
void LinkList<T>::Display()
{
Node<T>* tmp = _head;
while(tmp)
{
cout<<tmp->_data<<" ";
tmp = tmp->_next;
}
cout<<endl;
}
template<typename T,typename Container>
class Queue
{
public:
bool Empty()
{
return _con.GetHead() == NULL;
}
Node<T>& Front()
{
return *_con.GetHead();
}
void Back(const T& data)
{
}
void Push(const T& data)
{
_con.PushBack(data);
}
void Pop()
{
_con.PopFront();
}
void Dispaly()
{
while(!Empty())
{
cout<<Front()._data<<endl;
Pop();
}
}
private:
Container _con;
};
void test1()
{
Queue<int , LinkList<int> > s;
s.Push (1);
s.Push (1);
s.Push (1);
s.Push (2);
s.Dispaly ();
}
void test()
{
LinkList<int> l;
l.PushBack (1);
l.PushBack (4);
l.PushBack (2);
l.PushBack (1);
l.PushBack (2);
l.PushBack (6);
l.PushFront (4);
l.Sort ();
//l.Remove (1);
//l.RemoveAll (3);
//l.PopBack ();
/*l.PopBack ();
l.PushFront (4);
l.PopFront ();*/
l.Display ();
}
int main()
{
test1();
system("pause");
return 0;
}