如果两种类只是数据类型不同,而其他代码是相同的,与其编写新的类声明,不如编写一种泛型(独立于类型的)栈。然后将具体的类型作为参数传递给这个类。这样就可以使用通用的代码生成存储不同类型值的栈。

可以使用typedef处理这样的需求,但是有两个问题,一、每次修改类型都必须重新编辑头文件;二、在每个程序中都只能使用这种技术生成一种栈。

C++的类模板为生成通用的类声明提供了一种更好的方法;模板提供参数化类型,能够将类型名作为参数传递给接收方来建立类或函数。

C++标准模板库(STL)提供了几种功能强大而灵活的容器类模板。

定义模板类

template <class Type>,template告诉编译器,将要定义一个模板。尖括号内容相当于函数的参数列表。

也可以这么写:

template <typename Type>

或是:

template <class T>

template <typename T>

当模板被调用时,Type将被具体的类型值(int或string)取代。

原来类的声明:

typedef unsigned long Item;

class Stack

{

private:

enum {MAX = 10};

Item items[MAX];

int top;

public:

Stack( );

bool isempty( ) const;

bool isfull( ) const;

bool push (const Item & item);

bool pop(Item & item);

}

类模板信息必须都放在头文件中,不能把模板成员函数放到独立的实现文件中。因为模板不是函数,不能单独编译。在要使用这些模板的文件中包含该头文件。

类模板:

template<class Type>

Stack<Type>::Stack()

{

}

template <class Type>

bool Stack<Type>::isempty()

{

}

template <class Type>

bool Stack<Type>::isfull()

{

}

template <class Type>

bool Stack<Type>::push(const Type & item)

{

}

template <class Type>

bool Stack<Type>::pop(Type & item)

{

}

使用类模板

仅在程序包含模板并不能生成模板类,而必须请求实例化。需要声明一个类型为模板类的对象,并且使用所需的具体类型替换泛型名。

Stack<int> kernels;

Stack<string>colonels;

看到上述两个声明后,编译器将按Stack<Type>模板来生成两个独立的类声明和两组独立的类方法。

泛型标识符——Type——被称为类型参数,这意味着它类似于变量,但是赋给它们的不能是数字,而只能是类型。

必须,显式地提供所需的类型,这与常规的函数模板是不同的。

深入探讨模板类

可以将内置类型或对象作为类模板Stack<Type>的类型。指针也是可以的。但是如果不对程序做重大修改,将无法很好地工作。

创建不同的指针是调用程序的职责,而不是栈的职责。栈的任务是管理指针,而不是创建指针。

字符串本身永远不会移动,把字符串压入栈实际上是新建一个指向该字符串的指针,即创建一个指针,该指针的值是现有字符串的地址。

构造函数使用new创建一个用于保存指针的数组,析构函数删除该数组,而不是数组元素指向的字符串。

数组模板示例和非类型模板

常用作容器类,这是因为类型参数的概念非常适合于将相同的存储方案用于不同的类型。引入模板的主要动机是:容器类可提供重用的代码。

深入探讨模板设计和使用的其他几个方面。

具体来说,探讨一些非类型(或表达式)参数以及如何使用数组。

实现一种允许指定数组大小的简单数组模板:

方法一:在类中使用动态数组和构造函数参数来提供元素数目;->旧方法

方法二:使用模板参数来提供数组的大小;

模板头:template<class T, int n>

class 关键字标识这是类型参数,int指出n的类型为int,这是非类型参数,或表达式参数;

表达式参数有一些限制:可以是整型,枚举,引用或指针。

表达式参数的优点:使用自动变量维护内存栈,而不是用构造函数方法使用的new,delete来管理内存。

表达式参数的缺点:下面的声明将生成两个独立的类声明;

ArrayTP<double, 12> eggweights;

ArrayTP< double, 13> eggweights;

而构造函数的方法,就只要一份类声明。

另一个区别是:构造函数的方法更通用。数组大小是作为类数据成员存储在定义中。

模板多功能性

模板的作用:

用作基类

用作组件类

用作其他模板的类型参数

数组模板实现栈模板

数组模板来构造数组

递归使用模板

使用多个类型参数

template<class T1, class T2>

默认类型模板参数

可以为类型参数提供默认值;

template<class T1, class T2=int>

类模板:类型参数可提供默认值;

函数模板的类型参数不可听默认值;

非类型参数:类模板,函数模板都可以提供默认值;

模板的具体化

模板以泛型的方式描述类;

而具体化是使用具体的类型生成类声明;

1、 隐式实例化

是指在需要对象之前,不会生成类;

ArrayTP<double,30> * pt;  //一个指针,还没有对象被创建

pt = new ArrayTP<double,30>;  //创建一个对象

2、 显式实例化

template class ArrayTP<string,100>; //会产生一个类的实例,声明一个类;

虽然没有创建或提及类对象,编译器也将生成类声明。

3、 显式具体化

指的是特定类型的定义。

4、部分具体化

成员模板

模板可用作结构、类或模板类的成员。

类的成员(数据,方法)->都可以用模板表示;

而不仅仅是类用模板表示;

模板之中有模板,嵌套的;还可以在模板之外定义方法模板,成员模板;

将模板用作参数

将模板用作模板的参数;

模板包含类型参数和非类型参数:

template <template <typename T> class Thing>

template <typename T> class Thing  是模板的参数;

其中template <typename T> class  是参数模板(把模板作为参数用);是类型;

假设有以下声明:

Crab<King> legs;

Crab<King>是模板Crab具体的类型;模板参数是King,King也必须是一个模板类。

template <typename T>

class King {…};

模板类和友元

模板类声明也可以有友元。(友元:模板or非模板, 约束or非约束)

l  非模板友元;

l  约束模板友元,即友元的类型取决于类被实例化时的类型;

l  非约束模板友元,即友元的所有具体化都是类的每一个具体化的友元;

1、 模板类的非模板友元函数

在模板类中将一个常规函数声明为友元:

template <class T>

class HasFriend

{

public:

friend void counts();

};

counts()函数成为模板所有实例化的友元。例如,它将是类hasFriend<int>和HasFriend<string>的友元。该友元与所有模板实例化的对象都具有友元关系(一对多)。该函数不是通过对象调用,没有对象参数。

template <class T>

class HasFriend

{

public:

friend void report(HasFriend<T> &);

};

这一种带模板类参数的友元。这是一种一对一的友元关系,即该友元只是某个具体类型的模板的友元函数。

2、 模板类的约束模板友元函数

3、 模板类的非约束模板友元函数

普通类+普通友元 (一对一)友元-类而言

普通类+模板友元 (多对一)友元-类而言

模板类+普通友元 (一对多)友元-类而言

模板类+模板友元 (多对多)友元-类而言

模板别名(C++)

 

C++_代码重用5-类模板的更多相关文章

  1. C++_代码重用1-总览

    C++的主要目的是促进代码重用. 公有继承是实现这一目标的机制之一: 本身是另一个类的成员,这种方法称为包含.组合.层次化. 另一种方法是使用私有.保护继承. 通常包含.私有继承和保护继承用于实现ha ...

  2. C++_代码重用2-包含对象成员的类

    对于姓名可以使用字符数组来表示,但这将限制姓名的长度.当然,还可以使用char指针和动态内存分配,但这要求提供大量的支持代码.有一个好的方法就是使用一个他人开发好的类的对象来表示.如果C++库提供了合 ...

  3. C++_代码重用3-私有继承

    使用包含:易于理解,类声明中包含表示被包含类的显式命名对象,代码可以通过名称引用这些对象: 使用继承:将使关系更抽象,且继承会引起很多问题,尤其是从多个基类继承时. 私有继承所提供的特性确实比包含多. ...

  4. C++_代码重用4-多重继承

    继承使用时要注意,默认是私有派生.所以要公有派生时必须记得加关键字Public. MI(Multi Inheritance)会带来哪些问题?以及如何解决它们? 两个主要问题: 从两个不同的基类继承同名 ...

  5. C/C++:类模板

    类模板就是为类声明一种模板,使得类中的某些数据成员,或某些成员函数的参数,又或者是某些成员函数的返回值可以取任意的数据类型,包括基本数据类型和自定义数据类型. 类模板的声明形式如下: template ...

  6. C++解析(27):数组、智能指针与单例类模板

    0.目录 1.数组类模板 1.1 类模板高效率求和 1.2 数组类模板 1.3 堆数组类模板 2.智能指针类模板 2.1 使用智能指针 2.2 智能指针类模板 3.单例类模板 3.1 实现单例模式 3 ...

  7. C++中的单例类模板

    1,本节课讲述单例类模式,实现并抽取相关代码实现单例类模板,在以后开发工作 中,如果想要使用单例模式,那么直接使用今天开发的单例类模板就可以: 2,需求的提出: 1,在架构设计时,某些类在整个系统生命 ...

  8. C++_进阶之函数模板_类模板

     C++_进阶之函数模板_类模板 第一部分 前言 c++提供了函数模板(function template.)所谓函数模板,实际上是建立一个通用函数,其函数类型和形参类型不具体制定,用一个虚拟的类型来 ...

  9. 谈谈Delphi中的类和对象4---类是一种对数据和操作高度的封装机制 && 类是一种代码重用机制

    五.类是一种对数据和操作高度的封装机制 1)数据封装 unit Unit2; interface type TEmployee = class; private FName: String; publ ...

随机推荐

  1. JSP,PHP详细性能测试

    前几天在CU看到有人比较PHP与JSP,.net,结果表明PHP比JSP,.net性能低下很多.本人认为即使有差距,也不应该有这么大,所以认真测试一下几者间的性能差距.由于很久没用.net了,所以,暂 ...

  2. Vue.js 安装及其环境搭建

    For me or other first studying vue.js. For Windows PC: 1.先安装node.js 安装官网最新的即可 版本应该要大于6.0版本 nodejs的官网 ...

  3. 使用Monkey对APP进行随机测试

    Monkey测试简介 Monkey测试是Android平台自动化测试的一种手段,通过Monkey程序模拟用户触摸屏幕.滑动Trackball.按键等操作来对设备上的程序进行压力测试,检测程序多久的时间 ...

  4. 编写高质量代码改善C#程序的157个建议——建议1:正确操作字符串

    最近拜读了陆敏技老师的<编写高质量代码改善C#程序的157个建议>,感觉不错,决定把笔记整理一遍. 建议1: 正确操作字符串 字符串应该是所有编程语言中使用最频繁的一种基础数据类型.如果使 ...

  5. mysql 全文搜索 FULLTEXT

    到 3.23.23 时,MySQL 开始支持全文索引和搜索.全文索引在 MySQL 中是一个 FULLTEXT 类型索引.FULLTEXT 索引用于 MyISAM 表,可以在 CREATE TABLE ...

  6. POJ2442 Sequence(堆的骚操作)

    Description Given m sequences, each contains n non-negative integer. Now we may select one number fr ...

  7. poj2513 Fence Repair(小根堆)

    Description Farmer John wants to repair a small length of the fence around the pasture. He measures ...

  8. 四则运算(Java) 陈志海 邓宇

    目录 Github项目地址 PSP表格 功能要求 题目 功能(已全部实现) 效能分析 设计实现过程 数值生成 算式生成 问题集生成 设计实现过程 代码说明 测试运行 代码覆盖率 项目小结 Github ...

  9. 模板方法(Template Method)模式

    /* * 抽象模版(AbstractClass)角色有如下的责任: 定义了一个或多个抽象操作,以便让子类实现.这些抽象操作叫做基本操作,它们是一个顶级逻辑的组成步骤. 定义并实现了一个模版方法.这个模 ...

  10. React 使用browserHistory项目访问404问题

    最近项目里面用到了React但是发布到iis站点之后,路由地址 刷新访问直接404错误.查阅资料之后发现是iis缺少配置URL重写 的问题导致的.下面我们来图形化配置,简单的配置下IIS 打开IIS使 ...