模板是泛型編程的基礎,即與類型無關的邏輯代碼。
利用模板機制可以顯著減少冗余信息,能大幅度地節約程序代碼,進一步提高面向對象程序的可重用性和可維護性。
模板是實現代碼重用機制的一種工具,它可以實現類型參數化;
模板分為函數模板和類模板。
為了使用函數名相同,參數不同,返回值可同可不同的函數時,我們起初用了重載的方式。
#include<iostream>
using?namespace?std;int?add(int?a,int?b)
{return?a+b;
}double?add(double?a,double?b)
{return?a+b;
}int?main()
{cout<<"ret1="<<add(1,2)<<endl;cout<<"ret2="<<add(2.3,3.0)<<endl;getchar();return?0;
}
但是運用重載的方式寫起來比較不方便,尤其是重載的函數較多時,為了解決這類問題,我們用函數模板來實現這種功能。
#include<iostream>
using?namespace?std;
template?<class?T>
T?add(const?T&?a,const?T&?b)
{cout<<"type:"<<typeid(a).name()<<endl;???//顯示類型return?a+b;
}int?main()
{cout<<"ret1="<<add(1,2)<<endl;//還可以顯示實例化,顯示指定T為int,即add<int>(1,2)cout<<"ret2="<<add(2.3,3.0)<<endl;???//add<double>(2.3,3.0)getchar();return?0;
}
以上函數中函數參數類型都是相同的,當我們遇到形如:add(1,2.3);一個參數為int,一個參數為double型,此時我們可以這樣定義:
template?<class?T1,class?T2>
T?add(const?T1&?a,const?T2&?b)
{return?a+b;
}
當然,肯定有人會想,模板函數可以構成重載嗎?????答案是肯定的。
#include<iostream>
using?namespace?std;int?add(int?a,int?b)
{return?a+b;
}double?add(double?a,double?b)
{return?a+b;
}
template?<class?T>
T?add(const?T&?a,const?T&?b)
{cout<<"type:"<<typeid(a).name()<<endl;?return?a+b;
}int?main()
{cout<<"ret1="<<add(1,2)<<endl;cout<<"ret2="<<add(2.3,3.0)<<endl;getchar();return?0;
}
當模板構成重載,調用add的函數時,它會先調用非模板類的函數,性能比較高;而模板函數內部還得調用,有推演過程判斷它是什么類型,效率上會有所降低。
2.模板類
對于普通函數來說,我們拿typedef重定義一個類型,當需要改的時候,需要將int改掉就可以了;
typedef?int?DataType;class?SEQLIST
{
private:DataType?*data;
};
而我們為了適應更多的類型,于是引入了模板類,我們這樣定義,體現了其高度復用的優勢:
template<class?T>
class?SeqList
{
private:T*?data;
};
寫一個模板類實現SeqList的動態順序表吧:
#include<iostream>
using?namespace?std;template?<class?T>
class?SeqList
{
public:SeqList():_data(NULL),_size(0),_capacity(0){}SeqList(const?SeqList<T>&?s);SeqList<T>&?operator=(const?SeqList<T>&?s);~SeqList(){if(_data?!=?NULL){delete[]?_data;}}void?CheckCapacity();void?PushBack(const?T&?d);void?PopBack();void?PushFront(const?T&?d);void?PopFront();void?Print();
private:T?*_data;int?_size;int?_capacity;
};
template?<class?T>
SeqList<T>::SeqList(const?SeqList<T>&?s)
{_data?=?new?T[s._size*sizeof(T)];int?i?=?0;for(i?=?0;i?<?s._size;?i++){_data[i]?=?s._data[i];}_size?=?s._size;_capacity?=?s._capacity;
}
template?<class?T>
SeqList<T>&?SeqList<T>::operator=(const?SeqList<T>&?s)
{int?i?=?0;if(this?==?&s){return?*this;}_size?=?s._size;_capacity?=?s._capacity;delete?_data;_data?=?new?T[_capacity];for(i?=?0;?i?<?_size;?i++){_data[i]?=?s._data[i];}return?*this;
}
template?<class?T>
void?SeqList<T>::CheckCapacity()
{if(_size?==?_capacity){T*?tmp?=?new?T[_capacity*2+3];//memcpy(tmp,_data,_size*sizeof(T));int?i?=?0;for(i?=?0;?i?<?_size;?i++){tmp[i]?=?_data[i];}delete[]?_data;_data?=?tmp;_capacity?=?_capacity*2+3;}
}
template?<class?T>
void?SeqList<T>::PushBack(const?T&?d)
{CheckCapacity();_data[_size]?=?d;_size++;
}
template?<class?T>
void?SeqList<T>::PopBack()
{CheckCapacity();_size--;
}template?<class?T>
void?SeqList<T>::PushFront(const?T&?d)
{int?i?;CheckCapacity(); for(i?=?_size;?i?>?0;?i--){_data[i]?=?_data[i-1];}_data[0]?=?d;_size++;
}template?<class?T>
void?SeqList<T>::PopFront()
{int?i;CheckCapacity();for(i?=?0;?i?<?_size;?i++){_data[i]?=?_data[i+1];}_size--;
}
template?<class?T>
void?SeqList<T>::Print()
{int?i?=?0;for(i?=?0;?i?<?_size;?i++){cout<<_data[i]<<"?";}cout<<endl;
}int?main()
{SeqList<int>?seq;SeqList<int>?seq1;cout<<"seq:"<<endl;cout<<"尾插1234"<<endl;seq.PushBack(1);seq.PushBack(2);seq.PushBack(3);seq.PushBack(4);seq.Print();cout<<"尾刪"<<endl;seq.PopBack();seq.Print();cout<<"頭刪"<<endl;seq.PopFront();seq.Print();cout<<"seq2:"<<endl;SeqList<int>?seq2(seq);seq2.Print();cout<<"頭插567"<<endl;seq.PushFront(5);seq.PushFront(6);seq.PushFront(7);seq.Print();seq1?=?seq;cout<<"seq1:"<<endl;seq1.Print();getchar();return?0;
}
模板就說到這里啦,有好的建議還希望大家提出來,歡迎來訪哦。