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

时间: 2024-10-28 20:52:34

c++学习笔记啊——类模板(1)的相关文章

C++学习笔记36:类模板

类模板的目的 设计通用的类型式,以适应广泛的成员数据型式 类模板的定义格式 template<模板形式参数列表>class 类名称{...}; 原型:template<typename T> class A; 类模板的成员 像普通类的成员一样定义 定义在类中或类外均可,后者需要在类名后列些模板参数,以区别非模板类的成员函数 template<typename T> T A<T>::f(u) 类成员函数的模板 成员函数可以使用其他模板 template<

C++学习笔记(2)----类模板和友元

当一个类包含一个友元声明时,类与友元各自是否是模板是相互无关的.如果一个类模板包含一个非模板友元,则友元被授权可以访问所有模板实例.如果友元自身是模板,类可以授权给所有友元模板实例,也可以只授权给特定实例. 1. 一对一友好关系 类模板与另一个(类或函数)模板间友好关系的最常见形式是建立对应实例及其友元间的友好关系.例如,我们的 Blob 类应该讲 BlobPtr 类和一个模板版本的 Blob 相等运算符定义为友元. 为了引用(类或函数) 模板的一个特定实例,我们必须首先声明模板自身.一个模板声

C++学习笔记(3)----类模板的static成员

与任何其他类相同,类模板可以声明 static 成员: template <typename T> class Foo { public: static std::size_t count() { return ctr; } void addctr() { ctr++; } void subctr() { ctr--; } private: static std::size_t ctr; // 下面可以有其他成员接口 }; template <typename T> std::si

C++ Primer(第五版)学习笔记_1_标准模板库--快速入门

C++ Primer(第五版)学习笔记_1_标准模板库--快速入门 欢迎大家阅读参考,如有错误或疑问请留言纠正,谢谢 标准模板库(STL)提供三种类型的组件:容器.迭代器和算法,他们都支持泛型程序设计标准. 容器主要有两类:顺序容器和关联容器.顺序容器(vector.list.deque和string等)是一系列元素的有序集合.关联容器(set.multiset.map和multimap)包含查找元素的键值. 迭代器的作用是遍历容器. STL算法库包含四类算法:排序算法.不可变序算法.变序性算法

C++学习笔记十六-模板和泛型编程(二)

C++学习笔记十六-模板和泛型编程(二) 16.4 类模板成员 1.模板作用域中模板类型的引用: 通常,当使用类模板的名字的时候,必须指定模板形参.这一规则有个例外:在类本身的作用域内部,可以使用类模板的非限定名.例如,在默认构造函数和复制构造函数的声明中,名字 Queue 是 Queue<Type> 缩写表示.实质上,编译器推断,当我们引用类的名字时,引用的是同一版本.因此,复制构造函数定义其实等价于: Queue<Type>(const Queue<Type> &a

C++ Primer 学习笔记_19_类与数据抽象(5)_初始化列表(const和引用成员)、拷贝构造函数

C++ Primer 学习笔记_19_类与数据抽象(5)_初始化列表(const和引用成员).拷贝构造函数  从概念上将,可以认为构造函数分为两个阶段执行: 1)初始化阶段: 2)普通的计算阶段.计算阶段由构造函数函数体中的所有语句组成. 一.构造函数初始化列表 推荐在构造函数初始化列表中进行初始化 1.对象成员及其初始化 <span style="font-size:14px;">#include <iostream> using namespace std;

C++ Primer 学习笔记_14_标准模板库_bitset位集合容器

C++ Primer 学习笔记_14_标准模板库_bitset位集合容器 bitset容器是一个bit位元素的序列容器,每个元素只占一个bit位,取值为0或1,因而很节省内存空间.下图是一个bitset的存储示意图,它的10个元素只使用了两个字节的空间. 使用bitset需要声明头文件"#include <bitset>" 1.创建bitset对象 创建bitset对象时,必须要指定容器的大小.bitset对象的大小一经定义,就不能修改了.下面这条语句就定义了bitset对

C++ Primer 学习笔记_23_标准模板库_stack.

C++ Primer 学习笔记_11_标准模板库_stack.queue队列容器与priority_queue优先队列容器 1.stack堆栈 stack堆栈是一个后进先出(Last In First Out,LIFO)的线性表,插入和删除元素都只能在表的一端进行.插入元素的一端称为栈顶,而另一端称为栈底.插入元素叫入栈(Push),删除元素叫出栈(Pop).下图是堆栈示意图 堆栈只提供入栈,出栈,栈顶元素访问和判断是否为空等几种方法.采用push()方法将元素入栈:采用pop()方法出栈:采用

Java学习笔记_25_Collections类

25.Collections类: Collections类是一个工具类,用来对集合进行操作,它主要是提供一些排序算法,包括随机排序.反相排序等. Collections类提供了一些静态方法,实现了基于List容器的一些常用算法. Collections的一些方法列表: · void sort(List): 对List内的元素进行排序. · void shuffle(List): 对List内的元素随机排序. · void reverse(List): 对List内的元素进行逆序排列. · voi