转载http://blog.csdn.net/xinzheng_wang/article/details/6674847

泛型的基本思想:
泛型编程(Generic Programming)是一种语言机制,通过它可以实现一个标准的容器库。
像类一样,泛型也是一种抽象数据类型,但是泛型不属于面向对象,它是面向对象的补充和发展。
在面向对象编程中,当算法与数据类型有关时,面向对象在对算法的抽象描述方面存在一些缺陷。
比如对栈的描述:
class stack
{

push(参数类型)  //入栈算法

pop(参数类型)   //出栈算法

}
如果把上面的伪代码看作算法描述,没问题,因为算法与参数类型无关。但是如果把它写成可编译的源代码,
就必须指明是什么类型,否则是无法通过编译的。使用重载来解决这个问题,即对N种不同的参数类型写N个
push和pop算法,这样是很麻烦的,代码也无法通用。
若对上面的描述进行改造如下:
首先指定一种通用类型T,不具体指明是哪一种类型。
class stack<参数模板 T>
{

push(T)  //入栈算法

pop(T)   //出栈算法

}

这里的参数模板T相当于一个占位符,当我们实例化类stack时,T会被具体的数据类型替换掉。
若定义对象S为statc类型,在实例化S时若我们将T指定int型则:
这时候类S就成为:
class S
{
    push(int)  //入栈算法
    pop(int)   //出栈算法
}
这时我可以称class stack<参数模板 T>是类的类,通过它可以生成具体参数类型不同的类。
泛型在C++中的应用:
泛型在C++中的主要实现为模板函数和模板类。
通常使用普通的函数实现一个与数据类型有关的算法是很繁琐的,比如两个数的加法,要
考虑很多类型:
int add(int a,int b) { return a+b; }
float add(float a,float b) { return  a+b; }
。。。。
虽然在C++中可以通过函数重载来解决这个问题,但是反复写相同算法的函数是比较辛苦的,
更重要的是函数重载是静态编译,运行时占用过多内存。
在此我们可以用C++的模板函数来表达通用型的函数,如下:
template<typename T> // 模板声明
T add(T a,T b) { return a+b; }  // 注意形参和返回值的类型
这时C++编译器会根据add函数的参数类型来生成一个与之对应的带具体参数类型的函数并
调用。
例如:
#include <iostream>
using namespace std;
template <typename T>
T add(T a,T b)  //注意形参和返回类型
{   
 return a+b;

void main()
{
    int num1, num2, sum; 
    cin>>num1>>num2;
    sum=add(num1,num2); //用int匹配模版参数T,若sum,num1,num2类型不一致则无法匹配。
    cout<<sum;
}
函数模板的性质
1) 函数模板并不是真正的函数,它只是C++编译生成具体函数的一个模子。
2) 函数模板本身并不生成函数,实际生成的函数是替换函数模板的那个函数,比如上例中的add(sum1,sum2),
    这种替换是编译期就绑定的。
3) 函数模板不是只编译一份满足多重需要,而是为每一种替换它的函数编译一份。
4) 函数模板不允许自动类型转换。
5) 函数模板不可以设置默认模板实参。比如template <typename T=0>不可以。
C++模版函数的语法
template  <typename 模版参数列表…>
函数返回类型 函数名(形参列表…)
上面两行可以合并成一行。
例如:
下面的几种写法是等效的并且class 和typename是可以互换的。
template  <typename T1, typename T2>
T1 fun(T1, T2, int )
{  //…..}
template  <typename T1,T2>  T1 fun(T1, T2, int )
{  //…..}
template  <class T1, class T2>
 T1 fun(T1, T2, int )
{  //…..}
template  <class T1,T2>  T1 fun(T1, T2, int )
{  //…..}
C++模版类的语法
template  <class 模版参数列表…>
class 类名
{ //类体}
成员的实现…
例如:
//类声明部分,有两个模板参数T1,T2
template  <class T1, class T2 >  
class A {
   private:
   int a;
  T1 b;  //成员变量也可以用模板参数
  public: 
  int fun1(T1 x, int y );
 T2 fun2(T1 x, T2 y);
}
//类实现部分
template  <class T1, class T2 >
int A<T1>:: fun1(T1 x, int y ){//实现…… }
 template  <class T1, class T2 >
T2 A<T1,T2>:: fun2(T1 x, T2 y) {//实现…… }
 //使用类A
 int main( ) {
 //定义对象a,并用int替换T1, float替换T2
   A<int, float>  a;
   //实例化a,调用a的属性和方法……
}
由上例可以看出, 类模板参数T1,T2对类的成员变量和成员函数均有效。
在C++编程中,当你要实现的一个类的某些成员函数和成员变量的算法
数据类型有关,可以考虑用类模板。C++版的数据结构算法大都用类模板实现。
类模板的性质
1) 类模板不是真正的类,它只是C++编译器生成具体类的一个模子。
2) 类模板可以设置默认模板实参。
C++ STL简介
  STL(Standard Template Library,标准模板库)是C++对泛型编程思想的实现,最早是惠普实验室开发的。
在被引入C++之前该技术就已经存在了很长的一段时间。后来STL成为ANSI/ISO C++标准的一部分。各个
C++厂商也有各自相应的模板库,这些库效率可能很高,但可移植性不一定好。
  STL广义上分为三类:algorithm(算法)、container(容器)和iterator(迭代器),几乎所有的代码都采
用了模板类和模板函数的方式,这相比于传统的由函数和类组成的库来说提供了更好的代码重用机会。
  在C++标准中,STL被组织为下面的13个头文件:<algorithm>、<deque>、<functional>、<iterator>、<vector>、
<list>、<map>、<memory>、<numeric>、<queue>、<set>、<stack> 和<utility>。
1) 算法(algorithm)
  STL提供了大约100个实现算法的模版函数,算法部分主要由头文件<algorithm>,<numeric> 和<functional>组成。
  <algorithm>是所有STL头文件中最大的一个,它是由一大堆模板函数组成的,其中常用到的功能范围涉及到比较、
交换、查找、遍历操作、复制、修改、移除、反转、排序、合并等等。
  <numeric>体积很小,只包括一些简单数学运算的模板函数。
  <functional>中则定义了一些模板类,用以声明函数对象。
2)  容器(container)(又称集合collection)
  在实际的开发过程中,数据结构本身的重要性不会逊于操作于数据结构的算法的重要性,当程序中存在着对时间要
求很高的部分时,数据结构的选择就显得更加重要。
  通过设置一些模版类,STL容器对最常用的数据结构提供了支持,这些模板的参数允许指定容器中元素的数据类
型,可以将许多重复而乏味的工作简化。
如下表:

数据结构

实现头文件

向量(vector)

顺序性容器

<vector>

列表(list)

顺序性容器

<list>

双队列(deque)

顺序性容器

<deque>

集合(set)

关联容器

<set>

多重集合(multiset)

关联容器

<set>

栈(stack)

容器适配器

<stack>

队列(queue)

容器适配器

<queue>

优先队列(priority_queue)

容器适配器

<queue>

映射(map)

关联容器

<map>

多重映射(multimap)

关联容器

<map>

3)迭代器(iterator)
  迭代器是一种允许程序员检查容器内元素,并实现元素遍历的数据类型。C++标准库为每一种标准容器定义了一种迭代器类型。迭代器类型提供了比下标操作更一般化的方法:所有的标准库容器都定义了相应的迭代器类型,而只有少数的容器(比如数组)支持下标操作。因为迭代器对所有的容器都适用,现代C++程序更倾向于使用迭代器而不是下标操作访问容器元素。
  迭代器从作用上来说是STL最基本的部分,迭代器在STL中用来将算法和容器联系起来,起着一种黏和剂的作用。几乎STL提供的所有算法都是通过迭代器存取元素序列进行工作的,每一个容器都定义了其本身所专有的迭代器,用以存取容器中的元素。
  迭代器部分主要由头文件<utility>,<iterator> 和<memory>组成。<utility>是一个很小的头文件,它包括了贯穿使用在STL中的几个模板的声明,<iterator>中提供了迭代器使用的许多方法, <memory>为容器中的元素分配存储空间,同时也为某些算法执行期间产生的临时对象提供机制,<memory>中的主要部分是模板类allocator,它负责产生所有容器中的默认分配器。

4)

C++泛型基础学习的更多相关文章

  1. Java基础学习总结(83)——Java泛型总结

    1. 什么是泛型? 泛型(Generic type 或者 generics)是对 Java 语言的类型系统的一种扩展,以支持创建可以按类型进行参数化的类.可以把类型参数看作是使用参数化类型时指定的类型 ...

  2. 如何从零基础学习VR

    转载请声明转载地址:http://www.cnblogs.com/Rodolfo/,违者必究. 近期很多搞技术的朋友问我,如何步入VR的圈子?如何从零基础系统性的学习VR技术? 本人将于2017年1月 ...

  3. C#/.NET 基础学习

    初识C# C#是微软公司发布的面向对象的.运行于.NET Framework之上的高级程序设计语言.与Java有着明显不同,借鉴Delphi的特点,与COM(组件对象模型)直接集成,是微软公司 .NE ...

  4. [C# 基础知识梳理系列]专题六:泛型基础篇——为什么引入泛型

    引言: 前面专题主要介绍了C#1中的2个核心特性——委托和事件,然而在C# 2.0中又引入一个很重要的特性,它就是泛型,大家在平常的操作中肯定会经常碰到并使用它,如果你对于它的一些相关特性还不是很了解 ...

  5. Java基础学习笔记总结

    Java基础学习笔记一 Java介绍 Java基础学习笔记二 Java基础语法之变量.数据类型 Java基础学习笔记三 Java基础语法之流程控制语句.循环 Java基础学习笔记四 Java基础语法之 ...

  6. 一个小栗子聊聊JAVA泛型基础

    背景 周五本该是愉快的,可是今天花了一个早上查问题,为什么要花一个早上?我把原因总结为两点: 日志信息严重丢失,茫茫代码毫无头绪. 对泛型的认识不够,导致代码出现了BUG. 第一个原因可以通过以后编码 ...

  7. Java基础学习经验分享

    很多人学习Java,尤其是自学的人,在学习的过程中会遇到各种各样的问题以及难点,有时候卡在一个点上可能需要很长时间,因为你在自学的过程中不知道如何去掌握和灵活运用以及该注意的点.下面我整理了新手学习可 ...

  8. 尚学堂JAVA基础学习笔记

    目录 尚学堂JAVA基础学习笔记 写在前面 第1章 JAVA入门 第2章 数据类型和运算符 第3章 控制语句 第4章 Java面向对象基础 1. 面向对象基础 2. 面向对象的内存分析 3. 构造方法 ...

  9. Java:泛型基础

    泛型 引入泛型 传统编写的限制: 在Java中一般的类和方法,只能使用具体的类型,要么是基本数据类型,要么是自定义类型.如果要编写可以应用于多种类型的代码,这种刻板的限制就会束缚很多! 解决这种限制的 ...

随机推荐

  1. HTML学习案例--仿淘宝商品信息

    步骤:1.布局分析 2.敲代码 考察知识点: 1.类选择器(素材第四天) 2.CSS关于display,padding,margin的应用 3.如何用div布局 总结: 如果想让一行有两组以上的字块, ...

  2. C# 串口连接的读取与发送

    一.串口连接的打开与关闭 串口,即COM口,在.NET中使用 SerialPort 类进行操作.串口开启与关闭,是涉及慢速硬件的IO操作,频繁打开或关闭会影响整体处理速度,甚至导致打开或关闭串口失败. ...

  3. Redis性能篇(二)CPU核和NUMA架构的影响

    Redis被广泛使用的一个很重要的原因是它的高性能.因此我们必要要重视所有可能影响Redis性能的因素.机制以及应对方案.影响Redis性能的五大方面的潜在因素,分别是: Redis内部的阻塞式操作 ...

  4. 达梦数据库学习(一、linux操作系统安装及数据库安装)

    达梦数据库学习(一.linux操作系统安装及数据库安装) 环境介绍: 使用VM12+中标麒麟V7.0操作系统+达梦8数据库 一.linux系统搭建 本部分没有需要着重介绍,注意安装时基本环境选择&qu ...

  5. Ubuntu/Liinux睡眠无法唤醒解决方法:ACPI设置

    最近给笔记本换了一个固态,顺便就重装了一下系统,版本是Ubuntu 20.10.装完之后各种功能基本都是正常的,触摸板轻触单击.双指右键等功能开箱即用.但是在安装完最新的Nvidia驱动之后就出现了问 ...

  6. js 判断用户是手机端还是电脑端访问

    通过userAgent 判断,网页可以直接使用 navigation对象 node端 可以通过请求头的 ctx.request.header['user-agent'] const browser = ...

  7. 为linux添加一块新硬盘并分区

    一---如何增加一块硬盘1:虚拟机添加硬盘2:分区3:格式化4:挂载5:设置可以自动挂载 1---设置里面 2---分区命令 fdisk /dev/sdb开始分区m显示命令列表p显示磁盘分区 同fdi ...

  8. Centos 安装 Node-v12.17.0-linux-x64.tar.gz

    wget https://nodejs.org/dist/v12.17.0/node-v12.17.0-linux-x64.tar.gz tar -zxf node-v12.17.0-linux-x6 ...

  9. Windows环境下搭建FTP服务器

    Windows主机建立FTP服务器 第一步:启用对应的Windows功能 控制面板 选择启用或关闭Windows功能 勾选FTP服务器和Web管理工具 可能出现的问题 系统提示无法安装IIS和FTP服 ...

  10. Java并发包源码学习系列:阻塞队列实现之ArrayBlockingQueue源码解析

    目录 ArrayBlockingQueue概述 类图结构及重要字段 构造器 出队和入队操作 入队enqueue 出队dequeue 阻塞式操作 E take() 阻塞式获取 void put(E e) ...