模板
- 模板是泛型编程的基础,能够处理在编译时不知道类型的情况
(1)模板函数
- 模板函数(function template)
- 一个模板函数就是一个公式,可以用来生成针对特定类型的函数版本,如下compare模板的例子
1 template < typename T > 2 int compare(const T&v1,const T&v2) 3 { 4 //其实只要返回一个值,后面的就不会再执行了 5 if(v1v2) return 1; 6 return 0; 7 }
函数说明:
- 模板定义以关键字**template**开始
- 关键字之后的是模板参数列表,如果有多个参数,可以用逗号分开,且模板参数列表不能为空
总的来说:
compare函数声明了一个名为T的类型参数,在compare中我们用T来表示一种类型,而T的实际类型则是在编译时根据compare的使用情况来确定的。
(3)类模板
我们用栈类(stack)作为基础来建立模板
我们之前的一个stack的类声明如下
1 typedef unsigned long Item; 2 3 class stack 4 5 { 6 7 private: 8 enum{MAX=10}; 9 10 Item item[MAX]; 11 12 int top; 13 14 public: 15 16 //下面是一些栈类一些基本的方法 17 18 //构造函数 19 20 stack(); 21 22 //检验空栈,满栈 23 24 bool isempty() const; 25 26 bool isfull() const; 27 28 //入栈 29 30 bool push(const Item& item); 31 32 //出栈 33 34 bool pop(Item& item); 35 36 };
- 说明:语句typedef unsigned long Item;仅仅是为了编码的简单,他的意思是用Item来代替unsigned long
我们使用模板来编辑上述代码
首先,我们要告诉编辑器,我们这里定义一个模板
- 语句
template< typename Type >
- typename是变量名,标明Type是一个通用的变量说明符
- 当模板被调用时,Type将被具体的类型值(int或string取代)
其次,使用模板成员函数替换类方法
- 模板声明打头
- 修改限定符
具体代码片段
1 template < typename Type > 2 stack::stack() 3 { 4 top=0; 5 }
注意:
- 每一个函数实现上都要加上模板声明
- 不能将模板的成员函数放在独立的实现文件中,因为:模板不是函数,不能单独编译,模板必须与特定的模板实例化请求一起使用,最简单的就是放在一个头文件中
完整的头文件
1 //typedef unsigned long Item; 2 #ifndef STACK_H_ 3 #define STACK_H_ 4 template 5 //栈的操作准则:先进后出 6 class stack 7 { 8 private: 9 enum{MAX=10}; 10 //一个数组,每个类型都是unsigned long,这里是因为简单所以加了 11 //typedef unsigned long Item; 12 Type items[MAX]; 13 int top; 14 public: 15 //下面是一些栈类一些基本的方法 16 //构造函数 17 stack(); 18 //检验空栈,满栈 19 bool isempty() const; 20 bool isfull() const; 21 //入栈 22 bool push(const Type& item); 23 //出栈 24 bool pop(Type& item); 25 }; 26 27 template 28 stack::stack() 29 { 30 top=0; 31 } 32 33 template 34 bool stack::isempty() 35 { 36 //这是一个判断,千万别看错了 37 //两个== 38 return top==0; 39 } 40 41 template 42 bool stack::isfull() 43 { 44 return top==MAX; 45 } 46 47 template 48 bool stack::push(const Type&item) 49 { 50 if(top 51 bool stack::pop(Type&item) 52 { 53 if(top>0) 54 { 55 item = items[--top]; 56 return true; 57 } 58 else 59 return false; 60 } 61 #endif
使用类模板
我们在头文件中包含了模板,但是,要生成模板类还必须请求实例化,也就是需要声明一个类型为模板类的对象
语法:
stack< int >kernels;
stack< string >colonels;
说明:
- 编译器将按照stack< Type >模板生成两组独立的类声明和类方法
- 必须显示的提供所需类型
这里与函数模板不同,编译器可以根据函数的参数确定生成那个版本的函数,
代码片段——栈程序测试
1 #include< iostream> 2 #include< string> 3 //这个是干嘛的 4 #include< cctype> 5 #include"stack.h" 6 using std::cin; 7 using std::cout; 8 9 int main() 10 { 11 //模板类的实例化 12 //创造一个模板类对象 13 Stack st; 14 char ch; 15 std::string po; 16 cout<<"please enter A to add a purchase order.\n" 17 <<"p to process a PO,or Q to quit.\n"; 18 while(cin>>ch && toupper(ch)!=‘Q‘) 19 { 20 while(cin.get() !=‘\n‘) 21 continue; 22 if(!isalpha(ch)) 23 { 24 cout<<‘\a‘; 25 continue; 26 } 27 switch(ch) 28 { 29 case ‘A‘: 30 case ‘a‘: cout<<"enter a PO number to add: "; 31 cin>>po; 32 if(st.isfull()) 33 cout<<"stack already full\n"; 34 else 35 st.push(po); 36 break; 37 case ‘P‘: 38 case ‘p‘: if(st.isempty()) 39 { 40 cout<<"stack already empty\n"; 41 } 42 else 43 { 44 st.pop(po); 45 cout<<"po# "<<<" popped\n"; 46 break; 47 } 48 } 49 cout<<"please enter A to add a purchase order.\n" 50 <<"p to process a PO,or Q to quit.\n"; 51 } 52 cout<<"bye\n"; 53 return 0; 54 }
问题一:
while(cin.get() !=‘\n‘)
continue;
上述这两条语句的连用,是为了检查输入的完成,比如说,你输入了nihao
此时,ch的值是n(获取的是单个字符)语句cin.get() !=‘\n‘
会读取下一个字符,并对他进行判断,如果是换行符,跳出循环,如果不是,接着读取下一个字符,知道遇到换行符为止
问题二:
1 template < class Type > 2 bool Stack< Type >::push(const Type&item) 3 { 4 if(top< MAX) 5 { 6 items[top++]=item; 7 return true; 8 } 9 else 10 return false; 11 } 12 13 template < class Type > 14 bool Stack::pop(Type&item) 15 { 16 if(top>0) 17 { 18 item = items[--top]; 19 return true; 20 } 21 else 22 return false; 23 }
这两个是关于入栈出栈的函数实现,栈的特点是:先进后出,注意:入栈时时top++,也就是items[0],执行完items[top++]=item;,top自增一,items[top]也就指向栈的下一个内存区域,确保下次赋值不会覆盖已有内存,而在出栈是采用的是item = items[--top];先移动指针,再进行操作
问题三:
函数toupper()
功能:转换为大写字符。
时间: 2024-10-28 20:52:34