c++学习笔记啊——类模板(1)

模板

  • 模板是泛型编程的基础,能够处理在编译时不知道类型的情况

(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 }

函数说明:

  1. 模板定义以关键字**template**开始
  2. 关键字之后的是模板参数列表,如果有多个参数,可以用逗号分开,且模板参数列表不能为空

总的来说:

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 >
  1. typename是变量名,标明Type是一个通用的变量说明符
  2. 当模板被调用时,Type将被具体的类型值(int或string取代)

其次,使用模板成员函数替换类方法

  • 模板声明打头
  • 修改限定符

具体代码片段

1 template < typename Type >

2 stack::stack()

3 {

4     top=0;

5 }

注意:

 

  1. 每一个函数实现上都要加上模板声明
  2. 不能将模板的成员函数放在独立的实现文件中,因为:模板不是函数,不能单独编译,模板必须与特定的模板实例化请求一起使用,最简单的就是放在一个头文件中

完整的头文件

 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()功能:转换为大写字符。

 

你可能感兴趣的:(学习笔记)