模板入门学习
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;//... };轉載于:https://blog.51cto.com/10797127/1755480
總結
- 上一篇: VS2008 error PRJ000
- 下一篇: MFC CEdit 自动换行功能