/* * stacktp.h * * Created on: 2014年3月29日 * Author: */ /** * - 模板類的概念,與使用 * -# export template <class Type> * <li> export 關鍵字表示導出這個模板類,使用此關鍵,使得能夠把 * 模板類的聲明放在頭文件中,而定義分開放在.cpp的文件中. * 有些編譯器沒有實現此關鍵字,所以必須把定義與聲明放在頭文件中 * 不然編譯通不過 * </li> * <li> template 關鍵字,表示聲明一個模板類</li> * <li> <class Type> 表示要傳給這個模板類的參數 * class 這個關鍵字,表示參數的類型,這個關鍵字能夠用 Typename這個關鍵字替代 * Type 是參數的名字,也即變量名.C++習慣上用T表示 * 關鍵理解: * 咱們要抓住:"模板"和"模板類"這兩個概念. 有句話叫:依葫蘆畫飄瓢。意思是說按照葫蘆的樣子畫瓢。 * 用來類比的話就是說"模板"對應那個葫蘆,"類"對應那個瓢.同理,模板類的意思是告訴C++編譯器按 * 照模板類來生成具體的類代碼。具體的類代碼的函數和算法是相同的,不一樣的部分就是 <class Type> * 指定的那部分,這部分是編譯器要按照咱們使用時指定的參數的不一樣,編譯時生成相應的代碼,再也不須要 * 手寫和粘貼複製了.編譯器在幫程序員偷懶(從小的角度來看),提升一個層次來看,就叫通用編程.就是說 * 編寫一段通用的代碼,傳入什麼的樣的參數,就生成相應用的具體代碼。從數學的角度來講,就是寫了一個 * 公式或者說函數;不一樣的取值範圍和具體的量化,產生不一樣的結果。好比y=a+k(x),假如a,k是常量,根據x * 的取值不一樣,相應的y也不一樣。從這裏來理解,用模板寫一些算法性質的代碼,那簡值太妙了,特別是一些經常使用的 * 算法,能夠少死不少腦細胞. * </li> * -此類來自於C++ primer Plus(第五版)第14章 * -# 模擬實現一個堆棧,棧空間最大爲10 * * */ #ifndef STACKTP_H_ #define STACKTP_H_ // export template <class Type> template <class Type> class Stack { private: enum{MAX =10}; Type items[MAX]; int top; public: Stack(); bool isempty(); bool isfull(); bool push (const Type & item); bool pop (Type & item); }; /** *下面的書寫形式,要講一下 *template <class Type> //這一部分參考頭文件的說明 * Stack<Type>::Stack()//這裏要說一下 * Stack :表示模板類的類名 * <Type>:表示傳給這個模板類的類型類參數, * 編譯器根據它的意思來生成具體的代碼.如終強調一點,咱們寫的是 * 模板代碼。注意"模板"兩字。 * ::Stack():表示是Stack<Type>這個模板類的構造方法. * 回固一下知識。若是咱們本身寫了構造函數。那麼C++編譯器,就不會在編譯時偷偷的生成默認構造函數了. * */ template <class Type> Stack<Type>::Stack() { top =0; } template <class Type> bool Stack<Type>::isempty() { return top == 0; } template <class Type> bool Stack<Type>::isfull() { return top == MAX; } template <class Type> bool Stack<Type>::push(const Type &item) { if(top < MAX){ items[top++] = item; return true; } else{ return false; } } template <class Type> bool Stack<Type>::pop(Type & item) { if(top>0){ item = items[--top]; return true; } else{ return false; } } #endif /* STACKTP_H_ */
//============================================================================ // Name : TemplateClass_1.cpp // Author : // Version : // Copyright : Free // Description : Hello World in C++, Ansi-style //============================================================================ #include <iostream> #include <cstring> #include <cctype> using namespace std; #include "stacktp.h" int main() { /** * 注意:[1] * 咱們傳了std::string這個類型給Stack模板類 * 編譯器是如何知道Stack是個模板類呢,或者說咱們是如何確 * Stack是個模板類呢,而不是普通的類呢。注意"<>"這對尖括號 * 它表示類Stack還要接受一個類型參數,因此咱們從這裏肯定的。 * 編譯器也是經過<>來識別的。咱們其實能夠想象普通的非模板類, * 也有一對尖括號的,也接受了一個參數,只是這個參數在非模板類 * 的定義裏面沒有用到,沒有使用這個參數,因此傳了也沒有用。 * 這樣一想,能夠在概念上把非模板類和模板類統一認爲是模板類了。 * 非模板類,是模板類的一個子集。 * 注意:[2] * Stack<std::string> st; //這裏雖然只寫了一句,但實際編譯後不僅是這句話, * 而是以下一段代碼: * Stack<std::string> st = new Stack(); * 可是這裏有個前提條件,咱們必須有一個默認構造函數,不然C++編譯器不知道,怎樣 * 初始化這個st對象。而報語法錯誤. * 而在Java中,定義的對象都是引用。必需要new纔會初始化. * 所以咱們要記住一點,在面向對象的世界裏,全部的對象都要有初值,要有一個肯定的狀態. * 若是容許,對象有不肯定的狀態,那麼就沒有那麼了... * */ Stack<std::string> st; char ch; std::string po; cout <<"Please enter A to add a purchase order,\n" << "P to process a PO,or Q to quit.\n"; while(cin >> ch && std::toupper(ch)!= 'Q') { while(cin.get()!='\n') continue; if(!std::isalpha(ch)) { cout<< '\a'; continue; } switch(ch) { case 'A': case 'a': cout <<"Please Enter a PO number to add:"; cin>>po; if(st.isfull()) { cout << "stack already full\n"; } else { st.push(po); } break; case 'P': case 'p': if(st.isempty()) { cout << "stack already empty\n"; } else { st.pop(po); cout << "PO # "<<po<<" popped\n"; } break; } cout <<"Please enter A to add a purchase order,\n" << "P to process a PO,or Q to quit.\n"; } cout<< "Bye\n"; return 0; }