类模板与模板类

为什么要引入类模板:类模板是对一批仅仅成员数据类型不同的类的抽象,程序员只要为这一批类所组成的整个类家族创建一个类模板,给出一套程序代码,就可以用来生成多种具体的类,(这类可以看作是类模板的实例),从而大大提高编程的效率。

注意:

1、类模板是参数化的类,即用于实现数据类型参数化的类。

2、应用类模板可以使类中的数据成员、成员函数的参数及成员函数的返回值,能根据模板参数匹配情况取任意数据类型

语法:

//类模板的定义

    template <类型形参表>
class 类名
{
//类说明体
};

//类外成员函数的定义

    template <类型形参表>  //不要漏了啊。
返回值类型 类模板名<类型名表>::成员函数名(参数表)
{
//成员函数体
}

类模板的实例化:

类模板名 <实际类型>  对象名(实参表);  

具体的使用过程:

当类模板创建对象时,根据用户给出的实际类型,系统将类模板中的模板参数置换为确定的参数类型,生成一个具体的类(模板类),
有对象之后,和普通类的对象使用方法相同。  

注意:

1、模板类的成员函数必须是函数模板

2、类模板中的成员函数的定义,若放在类模板中,则与普通类的成员函数的定义方法相同;若在类模板之外定义,则成员函数的定义格式如上

书写代码时要注意 类模板和普通类的代码区别:

1、针对类整体而言,在类定义前必须有模板声明

2、针对类外定义的成员函数(每个函数都有)而言,定义时必须要冒(模板声明) + 在函数名前、类后必须加<Type>

3、针对类的对象而言,在建立对象时,必须在类名和对象之间要写实际类型<实际类型>

模板类的形参表:template <类型形参表>

模板形参表类似函数形参表,由类型、非类型和模板三部分组成。

类型形参:代表所有的数据类型-所有的均可代表(类类型+预定义类型)

格式:由 关键字class或typename + 名字 组成

例如:template <class T,class D>,其中T和D都是一个类型形参,名字可以有自己定义

用途:这三种形参作用一样,均可以模板类型形参可作为类型说明符用在模板中的任何地方,即可以用于指定反回类型,变量声明等。

替代时间:类模板的类型实参必须在实例化类对象的时候指定

说明:这里的class表示一类类型,T是在实例化时确定,它的替代可以是任何类型,即类类型,预定义数据类型,比较通用

非类型形参=内置类型形参:代表具体的一类(C++的标准数据类型的一种,如整型)

格式:由 标准数据类型 + 名字 组成

例如:template <int a, int b>,其中a和b都是非类型形参 或 如template<class T, int a>,T为类型参数,a为非类型参数

参数有三种情况:

1、整型或枚举类型

2、指针类型(包含普通对象的指针类型、函数指针类型、指向成员的指针类型)

3、引用类型(指向对象或指向函数的引用都是允许的)

有些常值不能作为有效的非类型实参,包括:

1、空指针常量

2、浮点型值

3、字符串

说明:

1、非类型形参在模板定义的内部是常量值,也就是说非类型形参在模板的内部是常量,或者说只能是右值,它们不能被取址,也不能被赋值

2、调用非类型模板形参的实参必须是一个常量表达式,或者是一个数,即它必须能在编译时计算出结果。

举例:

    template <class T, int size>
class A
{ };
A<int 10> a; //正确
int b;
A<int, b> a; //错误,b不是常量
const int c;
A<int, c> a; //正确,c是常量

非类型模板形参还可以使用缺省值

    template <class T, int Size=100>
class A
{ };
A<int>a;//使用缺省值,设置长度100
A<int,200>a;//不使用缺省值长度设置200

说明:

百度说,非类型形参一般不应用于函数模板

非类型模板形参的形参和实参间所允许的转换 <引用黄邦勇帅的总结。>

1、允许从数组到指针,从函数到指针的转换。如:template <int *a> class A{}; int b[1]; A<b> m;即数组到指针的转换

2、const修饰符的转换。如:template<const int *a> class A{}; int b; A<&b> m; 即从int *到const int *的转换。

3、提升转换。如:template<int a> class A{}; const short b=2; A<b> m; 即从short到int的提升转换

4、整值转换。如:template<unsigned int a> class A{}; A<3> m; 即从int到unsigned int的转换。

5、常规转换。

模板形参:一个模板作为另一个模板的参数

格式:

    template <class A,class B,template<class C> class D>
class E
{//类模板E的定义}

说明:

1、template<class C> class D 是一个模板。

2、定义一个模板E,其中有两个类型参数A和B,一个模板参数D。注意C有时候可以省略不写

模板参数使用说明:

1、首先要定义一个模板:用来实例化模板E的对象。

2、A和B可以是任意类型;但是D可以是程序员自己定义的,也可以是STL中的标准模板库

代码:

    //首先定义一个普通的模板
template<class T>
class Array
{
//模板Array的成员
};
//定义一个模板Container,参数列表:一个类型为T,另一个模板类型Seq
template<class T, template<class> class Seq>//这里Seq前面的<>没有写参数名字
class Container
{
Seq<T> seq;
... ...
};
//注意:注意Seq模板的声明并没有带模板参数的名字,因为这里我们不会用到这个参数,所以可以省略不写.

实例化:

    Container<int, Array> container;  

说明:模板第一个参数为int,第二个参数为自己定义的模板(注意这里Array也代表一个类型,用户自定义的数据类型)

    Container<int, vector<int>> container;  

说明:模板第一个参数为int,第二个参数为STL中提供的模板(注意要使用实例化后的类型,因为这里参数必须是类型)

不知道直接写vector能不能用,是不是直接写vector时,下面使用seq时,要加<int>:seq<int>,写了就不加<int>:seq.

等以后用到在确定下???

用途:这样定义一个泛化的容器,容器里所存储的对象也是泛化

分析:需要两个类型:

一个是代表容器类型,vector,list。

另一个是存放数据的类型,如int,string

这时就要使用模板的模板参数:模板参数本身含是一个模板

举例:

    template<class TElem,template<class Type
,class Allocator=allocator<Type>> class TContainer>
class MyContainer : public TContainer<TElem>
{ };

实例化时就可以:

    MyContainer<int,vector> myContainer;  

说明:这里参数也可以使用默认的参数,就像函数中的确省参数是一样的,如class Allocator=allocator<Type>

C++ 类模板基础知识的更多相关文章

  1. 类模板语法知识体系梳理(包含大量常犯错误demo,尤其滥用友元函数的错误)

    demo 1 #include <iostream> #include <cstdio> using namespace std; //template <typenam ...

  2. C++ 函数模板基础知识

    为什么要引入模板:为了避免代码重复,程序员可以编写脱离数据类型通用模板. 模板的分类:函数模板 + 类模板 注意:模板的声明或定义只能在全局,命名空间或类范围内进行.不能在函数内进行,比如不能在mai ...

  3. Django模板-基础知识

    上一篇中带参数的URLconf虽然可以做到传参动态显示内容,但是最终现实的内容还是硬编码到Python代码中的 def hours_ahead(request,phours): try: phours ...

  4. smarty模板基础知识

    1.定义 Smarty是一个使用php写出来的模板引擎,它分离了逻辑代码和外在的内容,提供了一种易于管理和使用的方法,用来将原本与html代码混杂在一起PHP代码逻辑分离. 简单的讲,目的就是要使PH ...

  5. 开发工具、Object类(java基础知识十一)

    1.常见开发工具介绍 * A:操作系统自带的记事本软件 * B:高级记事本软件 * C:集成开发环境 IDE     * (Integrated Development Environment) *  ...

  6. 构造方法,重载,static,math类(java基础知识七)

    1.构造方法概述和格式 * A:构造方法概述和作用     * 给对象的数据(属性)进行初始化 * B:构造方法格式特点     * a:方法名与类名相同(大小也要与类名一致)     * b:没有返 ...

  7. UML 类图基础知识记录

    UML类图关系(泛化 .继承.实现.依赖.关联.聚合.组合) 依赖(Dependency): 关联(Association): 聚合(Aggregation): 合成(Composition): 泛化 ...

  8. Es6对象的扩展和Class类的基础知识笔记

    /*---------------------对象的扩展---------------------*/ //属性简写 ,属性名为变量名, 属性值为变量的值 export default functio ...

  9. 正则表达式、Calendar类、SimpleDateFormat类、Date类、BigDecimal类、BigInteger类、System类、Random类、Math类(Java基础知识十四)

    1.正则表达式的概述和简单使用 * A:正则表达式(一个字符串,是规则)     * 是指一个用来描述或者匹配一系列符合某个语法规则的字符串的单个字符串.其实就是一种规则.有自己特殊的应用. * B: ...

随机推荐

  1. find结合rm删除或mv移动文件的方法

    删除过期的备份文件,多用find结合rm方法,可以使用-exec或xargs -exec rm -rf {} \; 或 find /home/mysqlbackup -name "*$thi ...

  2. 【转】通过xml处理sql语句时对小于号与大于号的处理转换

    当我们需要通过xml格式处理sql语句时,经常会用到< ,<=,>,>=等符号,但是很容易引起xml格式的错误,这样会导致后台将xml字符串转换为xml文档时报错,从而导致程序 ...

  3. #ifndef详解

    #ifndef 是"if not defined"的简写,是预处理功能(宏定义.文件包含.条件编译)当中的条件编译,可以根据是否已经定义了一个变量来进行分支选择,其作用是: 1.防 ...

  4. Linux设备模型:基础篇

    linux提供了新的设备模型:总线(bus).设备(device).驱动(driver).其中总线是处理器与设备之间通道,在设备模型中,所有的设备都通过总线相连:设备是对于一个设备的详细信息描述,驱动 ...

  5. 部署vCenter Server Appliance 6.7

    =============================================== 2019/4/14_第1次修改                       ccb_warlock == ...

  6. [How to]HBase集群备份方法--Replication机制

    1.简介 HBase备份的方法在[How to]HBase集群备份方法文章中已经有些介绍,但是这些方法都不是HBase本身的特性在支持,都是通过MR计算框架结合HBase客户端的方式,或者直接拷贝HB ...

  7. Mac安装Homebrew记录

    在终端输入: ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install) ...

  8. 激活函数--(Sigmoid,tanh,Relu,maxout)

    Question? 激活函数是什么? 激活函数有什么用? 激活函数怎么用? 激活函数有哪几种?各自特点及其使用场景? 1.激活函数 1.1激活函数是什么? 激活函数的主要作用是提供网络的非线性建模能力 ...

  9. python 全栈开发,Day43(引子,协程介绍,Greenlet模块,Gevent模块,Gevent之同步与异步)

    昨日内容回顾 I/O模型,面试会问到I/O操作,不占用CPU.它内部有一个专门的处理I/O模块.print和写log 属于I/O操作,它不占用CPU 线程GIL保证一个进程中的多个线程在同一时刻只有一 ...

  10. CSP 地铁修建 Kruskal (最小生成树+并查集)

    问题描述 A市有n个交通枢纽,其中1号和n号非常重要,为了加强运输能力,A市决定在1号到n号枢纽间修建一条地铁. 地铁由很多段隧道组成,每段隧道连接两个交通枢纽.经过勘探,有m段隧道作为候选,两个交通 ...