C++除了支持模板函数,还支持模板类。模板类的目的同样是将数据类型参数化。

声明模板类的语法为:

template<typename 数据类型参数 , typename 数据类型参数 , …> class 类名{
//TODO:
};

模板类和模板函数都是以 template 开头,后跟数据类型参数列表;数据类型参数不能为空,多个参数用逗号隔开。

一但声明了模板类,就可以用数据类型参数来声明类中的成员变量和成员函数。也就是说,原来使用C++内置类型(比如 int、float、char 等)的地方,都可以用类型参数来代替。

假如我们现在要定义一个类来表示坐标,要求坐标的数据类型可以是整数、小数和字符串,例如:

x = 、y =
x = 12.88、y = 129.65
x = "东京180度"、y = "北纬210度"

这个时候就可以使用模板类,请看下面的代码:

template<typename T1, typename T2>  //这里不能有分号
class Point{
private:
T1 x;
T2 y;
public:
Point(T1 _x, T2 _y): x(_x),y(_y){}
T1 getX();
void setX(T1 x);
T2 getY();
void setY(T2 y);
};

坐标 x 和 y 的数据类型不确定,借助模板类,就可以将数据类型参数化,否则就要定义多个类。

注意:模板头和类头是一个整体,可以换行,但是中间不能有分号。

上面是类的声明,还需要在类外定义成员函数。在类外定义成员函数时仍然需要带上模板头,语法为:

template<类型参数列表> 函数返回值类型 类名<类型参数列表>::函数名(参数列表){
//TODO:
}

下面对 Point 类的成员函数进行定义:

template<typename T1, typename T2>
T1 Point<T1, T2>::getX(){
return x;
}
template<typename T1, typename T2>
void Point<T1, T2>::setX(T1 x){
this->x = x;
}
template<typename T1, typename T2>
T2 Point<T1, T2>::getY(){
return y;
}
template<typename T1, typename T2>
void Point<T1, T2>::setY(T2 y){
this->y = y;
}

应当注意:在类外定义成员函数时,template 后面的类型参数列表要与类声明时的一致。

模板类的实例化

实例化模板类时,需要指明数据类型。例如:

Point<int, int> p1(, );
Point<int, float> p2(, 15.5);
Point<float, char*> p3(12.4, "东京180度");

与模板函数不同的是,模板类在实例化时必须显式地指明数据类型,编译器不能根据给定的数据推演出数据类型。下面的实例化代码是错误的:

Point p1(, );
Point p2(10.4, "东京180度");

至此,我们就可以定义模板类并实例化了。

将上面的代码整合起来,给出一个完整的示例:

#include <iostream>
using namespace std;
template<typename T1, typename T2> //这里不能有分号
class Point{
private:
T1 x;
T2 y;
public:
Point(T1 _x, T2 _y): x(_x),y(_y){}
T1 getX();
void setX(T1 x);
T2 getY();
void setY(T2 y);
};
template<typename T1, typename T2>
T1 Point<T1, T2>::getX(){
return x;
}
template<typename T1, typename T2>
void Point<T1, T2>::setX(T1 x){
this->x = x;
}
template<typename T1, typename T2>
T2 Point<T1, T2>::getY(){
return y;
}
template<typename T1, typename T2>
void Point<T1, T2>::setY(T2 y){
this->y = y;
}
int main(){
Point<int, int> p1(, );
cout<<"p1.x="<<p1.getX()<<", p1.y="<<p1.getY()<<endl; Point<int, char*> p2(, "东京180度");
cout<<"p2.x="<<p2.getX()<<", p2.y="<<p2.getY()<<endl; Point<float, float> *p = new Point<float, float>(10.6, 109.3);
cout<<"p->x="<<p->getX()<<", p->y="<<p->getY()<<endl;
return ;
}

注意代码第 44 行,当定义模板类的指针时,赋值号两边都需要指明具体的数据类型,且要保持一致。下面的写法是错误的:

//赋值号两边的数据类型不一致
Point<float, float> *p = new Point<float, int>(10.6, );
//赋值号右边没有指明数据类型
Point<float, float> *p = new Point(10.6, );

C++学习34 模板类的更多相关文章

  1. 学习C++ 模板类

    #include<iostream>#include<typeinfo>#include<cstring> using namespace std; class A ...

  2. C++学习三 模板类出错总结(Missing template arguments before 'L')

    一.模板类的说明 模板类有一个好处是可以放宽你输入的数据类型. 比如有这样的一个函数: int add(int x, int y) { return x+y; } 这个函数对于int类型的x,y才适合 ...

  3. 读书笔记_Effective_C++_条款四十三:学习处理模板化基类的名称

    背景是这样的,有两个不同的公司,然后想设计一个MessageSender,为这两个公司发送不同的消息,既支持明文发送SendClearText,也支持密文发送SendEncryptedText.一种思 ...

  4. C++学习笔记36:类模板

    类模板的目的 设计通用的类型式,以适应广泛的成员数据型式 类模板的定义格式 template<模板形式参数列表>class 类名称{...}; 原型:template<typenam ...

  5. C++ 模板学习 函数模板、类模板、迭代器模板

    使用模板能够极大到使得代码可重用. 记录一下,方便后续使用. 1. 函数模板,支持多种类型参数 #include <stdio.h> #include <math.h> //函 ...

  6. C++学习笔记(3)----类模板的static成员

    与任何其他类相同,类模板可以声明 static 成员: template <typename T> class Foo { public: static std::size_t count ...

  7. C++学习笔记(2)----类模板和友元

    当一个类包含一个友元声明时,类与友元各自是否是模板是相互无关的.如果一个类模板包含一个非模板友元,则友元被授权可以访问所有模板实例.如果友元自身是模板,类可以授权给所有友元模板实例,也可以只授权给特定 ...

  8. QCache 缓存(类似于map的模板类,逻辑意义上的缓存Cache,方便管理,默认类似于LRU的淘汰算法)

    最近在学习缓存方面的知识,了解了缓存(Cache)的基本概念,为什么要使用缓存,以及一些缓存算法(缓存替换),如LRU.LFU.ARC等等. 这些缓存算法的实现过程会使用一些基本的数据结构,如list ...

  9. C++:类模板与模板类

    6.3 类模板和模板类 所谓类模板,实际上是建立一个通用类,其数据成员.成员函数的返回值类型和形参类型不具体指定,用一个虚拟的类型来代表.使用类模板定义对象时,系统会实参的类型来取代类模板中虚拟类型从 ...

随机推荐

  1. 常用邮件 smtp pop

    常用的邮箱服务器(SMTP.POP3)地址.端口  sina.com: POP3服务器地址:pop3.sina.com.cn(端口:110) SMTP服务器地址:smtp.sina.com.cn(端口 ...

  2. Oracle中的不等于号

    今天碰到一个Oracle不等于的问题,最后搜索了一下,发现下面资料,拿来跟大家分享一下   关于Oracle中的不等于号: 在Oracle中, <> != ~= ^= 都是不等于号的意思. ...

  3. shopex 网店系统安装教程

    centos上配置shopex环境(LNMP)  安装包地址: http://download.csdn.net/detail/nanmu1258/9109297 软件默认下载至在/opt/local ...

  4. HBase(一): c#访问hbase组件开发

    HDP2.4安装系列介绍了通过ambari创建hbase集群的过程,但工作中一直采用.net的技术路线,如何去访问基于Java搞的Hbase呢? Hbase提供基于Java的本地API访问,同时扩展了 ...

  5. My second "last working day"

    时间真快,转眼硕士毕业已经快8年了. 今天是我的第二个last working day.也是我即将结束在外企工作的节点. 说来,毕业的时候,找工作,在确定了最后要去的单位之前,手头已经拿过了10家单位 ...

  6. mysql批量更新

    UPDATE ta INNER JOIN tb ON ta.id=tb.id SET ta.col1=tb.col1, ta.col2=tb.col2 以上代码用来批量更新mysql中的记录

  7. mysql命令行导入sql文件

    今天从windows上导出一个sql执行文件,再倒入到unbutn中,结果出现乱码,折腾7-8分钟, 解决方式 在导出mysql sql执行文件的时候,指定一下编码格式: 复制代码代码如下: mysq ...

  8. 【python】禁止print输出换行的方法

    print后用一个逗号结尾就可以禁止输出换行,例子如下 >>> i=0 >>> while i < 3: print i i+=1 0 1 2 禁止输出换行后 ...

  9. 关于jquery插件 入门

    关于 JavaScript & jQuery 的插件开发   最近在温故 JavaScript 的面向对象,于是乎再次翻开了<JavaScript高级程序设计>第3版,了解到其中常 ...

  10. 剑指offer系列35----序列化二叉树

    [题目] * 请实现两个函数,分别用来序列化和反序列化二叉树 * 1 / \ 2 3 /\ /\4 5 6 7 * * 序列化的结果是1,2,#,#,3,4,#,7,#,#,5,#,#,. * 而反序 ...