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. 怎么给ABBYY FineReader Mac导入图像

    ABBYY FineReader Pro for Mac作为ABBYY旗下重要的OCR文字识别软件之一,专为Mac用户定制,为各种各样的任务提供了单一.全面的解决方案,它是所有需要扫描和处理数字纸质文 ...

  2. ABBYY是怎么自定义主窗口的

    启动 ABBYY FineReader OCR文字设别软件时,将打开其主窗口.同时将显示任务窗口,可以启动内置或自定义自动化任务. 主窗口显示目前打开的 ABBYY FineReader 文档. ● ...

  3. linux包之procps之vmstat命令

    概述 [root@localhost ~]# rpm -qf /usr/bin/vmstatprocps-3.2.8-25.el6.x86_64 vmstat是一个很全面的性能分析工具,可以观察到系统 ...

  4. JQuery Pagenation 知识点整理——(function($){...})应用(20150517)

    首先:(function($){...})为Jquery提供的匿名函数: 代码实例(一) <script type="text/javascript"> (functi ...

  5. MySQL在一台db服务器上面如何启动多个实例 (转)

    安装过程省略过,源码安装请参考http://write.blog.csdn.net/postlist/1609043/all 整理自己的文档,发现以前做的例子,share下,欢迎大家提出改进意见. 一 ...

  6. ef 高级操作

    一:动态拼接条件查询 var expression = PredicateBuilder.True<OQC_MES_INF_UL_QMS_OFFLINE>(); SYS_ROLES_CON ...

  7. (转载)postgresql navicat 客户端连接验证失败解决方法:password authentication failed for user

    命令:su - postgres CREATE USER foo WITH PASSWORD 'secret'; ==================== 1.2个配置修改 postgresql.co ...

  8. (转)用Eclipse进行C++开发时Bianry not found的问题解决

    本文转载自:http://blog.csdn.net/baimafujinji/article/details/49722399 由于Visual Studio体积过于庞大,很多人选择在Eclipse ...

  9. Spring实战4:面向切面编程

    主要内容 面向切面编程的基本知识 为POJO创建切面 使用@AspectJ注解 为AspectJ的aspects注入依赖关系 在南方没有暖气的冬天,太冷了,非常想念北方有暖气的冬天.为了取暖,很多朋友 ...

  10. MVC:上传文件

    今天写了一个使用MVC上传的DEMO,很简单不超过10行代码.代码如下(关注重点,所以尽量精简掉其他代码): 项目结构