C++模板类[初步]
/* * 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; }
posted on 2014-03-29 17:43 EarlyBird 阅读(2665) 评论(0) 编辑 收藏 举报