C++ 模板 与 泛型编程

前言

模板有两种:类模板和函数模板 。模板是泛型编程的基础。

什么叫:泛型编程?

使用独立于特定类型的方式进行编程。也就是我们在编程的时候不明确的写上类型,而是使用一个模板参数来代表某种类型。

所以泛型编程就需要使用模板。泛型编程这种编程方法,主要使用于:容器、迭代器、算法 。比如C++著名的标准模板库中都是使用模板和泛型编程。

并且数据结构和算法,都是大量的使用泛型编程的。所以本篇博客介绍如何使用C++进行泛型编程,来编写一个简单的队列类。下两篇博客,我们来一个实战:使用泛型编程的方法编写顺序队列 和 链式队列。


下面,我们写一个小例子,来介绍什么是泛型编程。

示例讲解

现在我们来做这样的一个例子:使用泛型编程做一个队列类。

我们先创建一个 queue.h 文件 和 一个main.cpp 文件。

先将下面的代码复制到 queue.h 文件里面。

#include<iostream>
#include <iomanip> using namespace std; //template<class T> class Queue{ struct Node{
int a;
Node * next;
};
public:
Queue();
~Queue();
void push(int b);
void pop();
int getlength();
virtual void print(); private:
Node * head;
Node * rear;
int num;
}; void Queue::push(int b){
Node *pl = new Node;
pl->a = b;
pl->next = NULL;
rear->next = pl;
rear = pl;
num++;
cout << setw(2) << b << setw(2) << " 进入队列 " << endl;
} void Queue::pop(){
Node *p;
p = head->next;
cout << " " << setw(2) << p->a << setw(2) << " 出队 " << endl;
head->next = p->next;
delete p;
num--;
} int Queue::getlength(){
return num;
} void Queue::print(){
Node *p;
p = head->next;
cout << "队列中的元素是:" << endl;
while(p){
cout << p->a << " -> ";
p = p->next;
}
cout << "NULL" << endl;
} Queue::Queue(){
rear = head = new Node();
} Queue::~Queue(){
delete head;
}

接着在 main.cpp 文件里面添加下面的代码,来测试 queue.h 里面的 Queue 类。

#include <iostream>
#include "queue.h" using namespace std; int main(){
Queue q;
q.push(10);
q.push(20);
q.push(30);
q.print(); system("pause");
return 0;
}

运行,输出结果:

10 进入队列
20 进入队列
30 进入队列
队列中的元素是:
10 -> 20 -> 30 -> NULL
请按任意键继续. . .

因为我们在设计这个 Queue 类的时候,它只能保存整数类型(int),而且类里面的所有操作也都是对整数进行操作的。那么这个队列就只能处理整数。如果,现在我们想把小数放到队列里面,那程序编译的时候就会出错;如果现在想把字符串放到队列里面来,就更不行了。

所以,这样编写的Queue 类就带来的一个麻烦,因为这个队列类只能处理整数类型的数据,它是一个整数队列。

如果我们现在想要一个处理字符串的队列,很不好的方法是:再添加一个.h 文件,然后写一个处理字符串的队列类。

世界上的数据类型很多,比如:intdoublestring、各种类、float等等。那我们岂不是要设计很多整队列类吗。

所以这个方法是不可取的。


应该怎么做呢?

这个时候,就有了模板编程。

template<class T>

这个 T 表示一个占位符,是任何一种类型的代表。这个T 就叫做:泛型

queue.h

#include<iostream>
#include <iomanip> using namespace std; template<class T>
class Queue{ struct Node{
T a;
Node * next;
};
public:
Queue();
~Queue();
void push(T b);
void pop();
int getlength();
virtual void print(); private:
Node * head;
Node * rear;
int num;
}; template<class T>
void Queue<T>::push(T b){
Node *pl = new Node;
pl->a = b;
pl->next = NULL;
rear->next = pl;
rear = pl;
num++;
cout << setw(2) << b << setw(2) << " 进入队列 " << endl;
} template<class T>
void Queue<T>::pop(){
Node *p;
p = head->next;
cout << " " << setw(2) << p->a << setw(2) << " 出队 " << endl;
head->next = p->next;
delete p;
num--;
} template<class T>
int Queue<T>::getlength(){
return num;
} template<class T>
void Queue<T>::print(){
Node *p;
p = head->next;
cout << "队列中的元素是:" << endl;
while(p){
cout << p->a << " -> ";
p = p->next;
}
cout << "NULL" << endl;
} template<class T>
Queue<T>::Queue(){
rear = head = new Node();
} template<class T>
Queue<T>::~Queue(){
delete head;
}

main.cpp

#include <iostream>
#include "queue.h" using namespace std; int main(){
Queue<int> q;
q.push(10);
q.push(20);
q.push(30);
q.print(); Queue<string> qs;
qs.push("www");
qs.push("aobosir");
qs.push("com");
qs.print(); qs.pop();
qs.print(); system("pause");
return 0;
}

注意:但凡是使用到模板参数的函数,在其前面都要添加上这段代码:template<class T>

使用 template<class T> 设计的类,就叫做类模板。

在编程的时候,我们没有指定具体的类型;在使用的时候,我们指定具体的类型。那么这种编程方法,就叫做:泛型编程。它所用到的就是:模板

使用这种方法来做编程的话,我只需要一个类模板,然后就可以处理任何一种类型的数据。(因为 T 就代表任何一种类型的数据。)

总结: 如果不使用泛型编程,那么只能设计一个处理具体类型的队列类。但是我们需要各种类型的,所以学会泛型编程,对以后使用C++ 编写数据结构和算法是非常有用的。

一个模板将所有的类型就都包括了。



接下来的两篇博客,我们会写两个例子:

一个是顺序队列 (里面是使用数组实现的,所以叫:顺序队列)

一个是链式队列(里面是使用链表实现的,所以叫:链式队列)

C++ 模板 与 泛型编程的更多相关文章

  1. C++ 模板与泛型编程

    <C++ Primer 4th>读书笔记 所谓泛型编程就是以独立于任何特定类型的方式编写代码.泛型编程与面向对象编程一样,都依赖于某种形式的多态性. 面向对象编程中的多态性在运行时应用于存 ...

  2. C++ Primer 学习笔记_76_模板与泛型编程 --模板定义[续]

    模板与泛型编程 --模板定义[续] 四.模板类型形參 类型形參由keywordclass或 typename后接说明符构成.在模板形參表中,这两个keyword具有同样的含义,都指出后面所接的名字表示 ...

  3. C++ Primer 学习笔记_84_模板与泛型编程 --模板特化

    模板与泛型编程 --模板特化 引言: 我们并不总是能够写出对全部可能被实例化的类型都最合适的模板.某些情况下,通用模板定义对于某个类型可能是全然错误的,通用模板定义或许不能编译或者做错误的事情;另外一 ...

  4. C++ Primer 学习笔记_77_模板与泛型编程 --实例化

    模板与泛型编程 --实例化 引言: 模板是一个蓝图,它本身不是类或函数.编译器使用模板产生指定的类或函数的特定版本号.产生模板的特定类型实例的过程称为实例化. 模板在使用时将进行实例化,类模板在引用实 ...

  5. C++ Primer 学习笔记_85_模板与泛型编程 --模板特化[续]

    模板与泛型编程 --模板特化[续] 三.特化成员而不特化类 除了特化整个模板之外,还能够仅仅特化push和pop成员.我们将特化push成员以复制字符数组,而且特化pop成员以释放该副本使用的内存: ...

  6. C++ Primer 学习笔记_75_模板与泛型编程 --模板定义

    模板与泛型编程 --模板定义 引言: 所谓泛型程序就是以独立于不论什么特定类型的方式编写代码.使用泛型程序时,我们须要提供详细程序实例所操作的类型或值. 模板是泛型编程的基础.使用模板时能够无须了解模 ...

  7. C++ Primer 学习笔记_76_模板和泛型编程 --模板定义[继续]

    模板和泛型编程 --模板定义[续] 四.模板类型形參 类型形參由keywordclass或 typename后接说明符构成.在模板形參表中,这两个keyword具有同样的含义,都指出后面所接的名字表示 ...

  8. C++ Primer 学习笔记_79_模板与泛型编程 --模板编译模型

    模板与泛型编程 --模板编译模型 引言: 当编译器看到模板定义的时候,它不马上产生代码.仅仅有在用到模板时,假设调用了函数模板或定义了模板的对象的时候,编译器才产生特定类型的模板实例. 一般而言,当调 ...

  9. c++模板 与 泛型编程基础

    C++模板 泛型编程就是以独立于任何特定类型的方式编写代码,而模板是泛型编程的基础. (1)定义函数模板(function template) 函数模板是一个独立于类型的函数,可以产生函数的特定类型版 ...

  10. C++ Primer(6) 模板和泛型编程(上)

    问题聚焦: 泛型编程是独立于变量类型的方式编写代码: 模板是泛型编程的基础. 本篇主要介绍模板的基础知识,包括:模板的定义和模板的实例化. 1 模版定义 必要性: Demo int compare(c ...

随机推荐

  1. 【备忘录】CentOS服务器mysql忘记root密码恢复

    mysql的root忘记,现无法操作数据库 停止mysql服务service  mysql stop 然后使用如下的参数启动mysql, --skip-grant-tables会跳过mysql的授权 ...

  2. 系统管理员都要知道的 30 个 Linux 系统监控工具

    1. top - 进程活动监控命令 top 命令会显示 Linux 的进程.它提供了一个运行中系统的实时动态视图,即实际的进程活动.默认情况下,它显示在服务器上运行的 CPU 占用率最高的任务,并且每 ...

  3. spring-session之四:Spring Session下的Redis存储结构

    spring-session项目启动后 127.0.0.1:6379> keys * 1) "spring:session:index:org.springframework.sess ...

  4. ConditionObject分析

      ConditionObject是AQS中的内部类,提供了条件锁的同步实现,实现了Condition接口,并且实现了其中的await(),signal(),signalALL()等方法. Condi ...

  5. Hadoop Map/Reduce的工作流

    问题描述 我们的数据分析平台是单一的Map/Reduce过程,由于半年来不断地增加需求,导致了问题已经不是那么地简单,特别是在Reduce阶段,一些大对象会常驻内存.因此越来越顶不住压力了,当前内存问 ...

  6. 线程的run( ) 和 start( ) 区别

    Run() :  run()就是个普通方法,可以调用执行,但是是同步调用,没有异步的效果. Run()方法就是个普通方法,可以调用多次 Start():  通知线程规划期,此线程已经准备就绪,等待调用 ...

  7. Mybatis扩展

    分页插件PageHelper 其实Mybstis内部有实现逻辑分页的功能,但是较为麻烦和难用.这里记录一个分页插件PageHelper的使用,我们可以在它的github地址https://github ...

  8. GDI/GDI+这些破事

    本文是杂篇,纯属笔记,想到哪写到那! 1.获取像素的RGB以及填充 CPaintDC dc(m_hWnd); COLORREF color=dc.GetPixel(,); int R=GetRValu ...

  9. php.ini文件中的include_path设置

    下面以安装smarty为例: 下面内容中,我们都是假设你的文件放在了D:\Appserv\www\Smarty下. 1.找到你的php.ini配置文件修改php.ini的include_path选项, ...

  10. css伪类(Pseudo-classes)

    简介:伪类(Pseudo classes)是选择符的螺栓,用来指定一个或者与其相关的选择符的状态.它们的形式是selector:pseudo class { property: value; },简单 ...