C++_代码重用5-类模板
如果两种类只是数据类型不同,而其他代码是相同的,与其编写新的类声明,不如编写一种泛型(独立于类型的)栈。然后将具体的类型作为参数传递给这个类。这样就可以使用通用的代码生成存储不同类型值的栈。
可以使用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-类模板的更多相关文章
- C++_代码重用1-总览
C++的主要目的是促进代码重用. 公有继承是实现这一目标的机制之一: 本身是另一个类的成员,这种方法称为包含.组合.层次化. 另一种方法是使用私有.保护继承. 通常包含.私有继承和保护继承用于实现ha ...
- C++_代码重用2-包含对象成员的类
对于姓名可以使用字符数组来表示,但这将限制姓名的长度.当然,还可以使用char指针和动态内存分配,但这要求提供大量的支持代码.有一个好的方法就是使用一个他人开发好的类的对象来表示.如果C++库提供了合 ...
- C++_代码重用3-私有继承
使用包含:易于理解,类声明中包含表示被包含类的显式命名对象,代码可以通过名称引用这些对象: 使用继承:将使关系更抽象,且继承会引起很多问题,尤其是从多个基类继承时. 私有继承所提供的特性确实比包含多. ...
- C++_代码重用4-多重继承
继承使用时要注意,默认是私有派生.所以要公有派生时必须记得加关键字Public. MI(Multi Inheritance)会带来哪些问题?以及如何解决它们? 两个主要问题: 从两个不同的基类继承同名 ...
- C/C++:类模板
类模板就是为类声明一种模板,使得类中的某些数据成员,或某些成员函数的参数,又或者是某些成员函数的返回值可以取任意的数据类型,包括基本数据类型和自定义数据类型. 类模板的声明形式如下: template ...
- C++解析(27):数组、智能指针与单例类模板
0.目录 1.数组类模板 1.1 类模板高效率求和 1.2 数组类模板 1.3 堆数组类模板 2.智能指针类模板 2.1 使用智能指针 2.2 智能指针类模板 3.单例类模板 3.1 实现单例模式 3 ...
- C++中的单例类模板
1,本节课讲述单例类模式,实现并抽取相关代码实现单例类模板,在以后开发工作 中,如果想要使用单例模式,那么直接使用今天开发的单例类模板就可以: 2,需求的提出: 1,在架构设计时,某些类在整个系统生命 ...
- C++_进阶之函数模板_类模板
C++_进阶之函数模板_类模板 第一部分 前言 c++提供了函数模板(function template.)所谓函数模板,实际上是建立一个通用函数,其函数类型和形参类型不具体制定,用一个虚拟的类型来 ...
- 谈谈Delphi中的类和对象4---类是一种对数据和操作高度的封装机制 && 类是一种代码重用机制
五.类是一种对数据和操作高度的封装机制 1)数据封装 unit Unit2; interface type TEmployee = class; private FName: String; publ ...
随机推荐
- 刷题向》关于搜索+tarjan的奇怪组合题 BZOJ1194 (normal+)
关于这道题,其实看懂了的话还是比较好写的,只是题目实在又臭又长,没有让人读下去的勇气. 给出题目翻译: 给你S张图, 每张图有M个点,其中M个点中有N个是特殊单位,会给出. 每个点又有0.1两条边指向 ...
- linux 压力测试工具 webbench
webbench最多可以模拟3万个并发连接去测试网站的负载能力,个人感觉要比Apache自带的ab压力测试工具好,安装使用也特别方便. 1.适用系统:Linux 2.编译安装: 1. wget htt ...
- web Servise(服务)
服务层:对项目的业务层(业务层调用数据层)的一个包装成对外的服务,是的UI展示可以从单一的WEB扩展为移动端可WINDFROM端等,这叫做面向服务的编程思想. 发布:和网站发布也是一样的. //web ...
- struts2 与 spring 整合
1. 首先把所有jar包导入工程 2.在struts2的核心配置文件(在src文件目录下)中添加如下配置: <!-- 将Struts的对象交给Spring管理 所以需要导入Spring和Stru ...
- SQLAlchemy(ORM框架)
SQLAlchemy SQLAlchemy概述 2 3 4 5 6 7 8 9 10 11 12 13 MySQL-Python mysql+mysqldb://<user>:&l ...
- 数组 array 矩阵 list 数据框 dataframe
转自 : http://blog.csdn.net/u011253874/article/details/43115447 <span style="font-size:14px;& ...
- dev 官网
https://www.devexpress.com/Support/Center/Example/Details/E1343 <%@ Page Language="C#" ...
- [.net 多线程]Barrier
当需要[一组任务]并行地运行一连串的阶段,但是每一个阶段都要等待所有他任务完成前一阶段之后才能开始,可以通过Barrier实例来同步这一类协同工作.Barrier初始化后,将等待特定数量的信号到来,这 ...
- 用C语言构建一个可执行程序的流程
1.流程图 从用C语言写源代码,然后经过编译器.连接器到最终可执行程序的流程图大致如下图所示. 2.编译流程 首先,我们先用C语言把源代码写好,然后交给C语言编译器.C语言编译器内部分为前端和后端. ...
- Java程序员修炼之路
作者简介:王成委,CSDN知识库特邀编辑,Java高级工程师,熟悉Java编程语言和Oracle数据库.专注于高并发架构设计和大数据存储方向的研究. 我们为什么选择Java 大多数人选择Java可能只 ...