与函数模板类似地(C++模板详解(一):函数模板的概念和特性) ,类也可以被一种或多种类型参数化。例如,容器类就是一个具有这种特性的典型例子,它通常被用于管理某种特定类型的元素。只要使用类模板,我们就可以实现容器类,而不需要确定容器中元素的类型。

一、类模板的实现

在这篇博文中,我们使用Stack作为类模板的例子。

(1.1) 类模板的声明

#include <vector>
#include <deque>
#include <stdexcept> template<typename T>
class Stack
{
std::vector<T> elems; // 存储元素的容器。 public:
void push(const T& value); // 将元素压入栈中。
void pop(); // 将栈顶元素弹出栈。
T top() const; // 查看栈顶元素的副本。
bool empty() const { // 检查栈是否为空。
return elems.empty();
}
}; template<typename T>
void Stack<T>::push(const T& value)
{
elems.push_back(value);
} template<typename T>
void Stack<T>::pop()
{
if (elems.empty()) {
throw std::out_of_range("Stack<>::pop(): empty stack");
}
elems.pop_back();
} template<typename T>
T Stack<T>::top() const
{
if (elems.empty()) {
throw std::out_of_range("Stack<>::pop(): empty stack");
}
return elems.back();
}

如上所示,类模板的声明和函数模板的声明很相似:在声明之前,我们先声明参数类型的标识符

template<typename /*class*/ T>
class Stack
{
//...
};

当然,也可以使用关键字class来代替typename。在类模板的内部,类型T可以像其它的类型一样,用于声明成员变量和成员函数。在这个例子中,类的类型是Stack<T>,其中T是模板参数。因此,当在声明中需要使用该类的类型时,我们必须要使用Stack<T>。例如,如果要声明自己实现的拷贝构造函数和赋值运算符,那就应该这样来编写:

template<typename T>
class Stack
{
//...
Stack(const Stack<T>& other); // 这里的构造函数名称需要与类名相同(Stack)
Stack<T>& operator=(const Stack<T>& other); // 这里的拷贝构造函数需要使用类的类型(Stack<T>)
//...
};

然而, 当需要使用类名而不是类的类型时,就应该只用Stack。例如,当指定类的名称,或是需要编写构造函数、析构函数时,就需要使用Stack

(1.2) 类模板的实现

为了定义类模板的成员函数,我们必须要指定该成员函数是一个函数模板(使用template<typename T>),而且还需要使用这个类模板的完整类型限定运算符Stack<T>::。因此,成员函数push的完整定义如下:

template<typename T>
void Stack<T>::push(const T& value)
{
elems.push_back(value);
}

其它成员函数的实现也是类似的;和普通类定义相同,完全也可以将成员函数的实现内联地写在类中,例如:

template<typename T>
class Stack
{
std::vector<T> elems; // 存储元素的容器。 public:
// ...
bool empty() const { // 检查栈是否为空。
return elems.empty();
}
};

二、类模板的使用

参见如下的main函数代码:

int main()
{
try
{
Stack<int> intStack;
Stack<std::string> stringStack; // 使用int栈
intStack.push(7);
std::cout << intStack.top() << std::endl; // 使用string栈
stringStack.push("hello");
std::cout << stringStack.top() << std::endl; stringStack.pop();
stringStack.pop();
}
catch (std::exception &ex)
{
std::cerr << "Exception: " << ex.what() << std::endl;
return EXIT_FAILURE;
}
return 0;
}

注意:只有那些被调用了的成员函数,才会产生这些函数的实例化代码。

所以,针对这个类模板,缺省的构造函数、pushtop方法都针对intstd::string进行了实例化。然而, pop方法只提供了std::string的实例化。这样做的好处是:

  • 可以节省时间和空间。
  • 对于那些未能提供所有成员函数中所有操作的类型,也可以使用该类型来实例化类模板。

另一方面,如果类中含有静态成员,那么用来实例化的每种类型,都会实例化这些静态成员。

C++ 类模板详解(一):概念和基本使用方式的更多相关文章

  1. C++ 函数模板&类模板详解

    在 C++ 中,模板分为函数模板和类模板两种.函数模板是用于生成函数的,类模板则是用于生成类的. 函数模板&模板函数     类模板&模板类  必须区分概念 函数模板是模板,模板函数时 ...

  2. 28.C++- 单例类模板(详解)

    单例类 描述 指在整个系统生命期中,一个类最多只能有一个实例(instance)存在,使得该实例的唯一性(实例是指一个对象指针)  , 比如:统计在线人数 在单例类里,又分为了懒汉式和饿汉式,它们的区 ...

  3. 25.C++- 泛型编程之函数模板(详解)

    本章学习: 1)初探函数模板 2)深入理解函数模板 3)多参函数模板 4)重载函数和函数模板 当我们想写个Swap()交换函数时,通常这样写: void Swap(int& a, int&am ...

  4. C++模板详解(三):参数化声明详解

    在前两节中(C++模板详解(一).C++模板详解(二)),我们了解了函数模板和类模板的基本概念和使用方法.在这篇博文里,我们主要来详细地阐述一下"模板的参数声明"这个话题,并且也谈 ...

  5. C++模板详解

    参考:C++ 模板详解(一) 模板:对类型进行参数化的工具:通常有两种形式: 函数模板:仅参数类型不同: 类模板:   仅数据成员和成员函数类型不同. 目的:让程序员编写与类型无关的代码. 注意:模板 ...

  6. 26.C++- 泛型编程之类模板(详解)

    在上章25.C++- 泛型编程之函数模板(详解) 学习了后,本章继续来学习类模板   类模板介绍 和函数模板一样,将泛型思想应用于类. 编译器对类模板处理方式和函数模板相同,都是进行2次编译 类模板通 ...

  7. UML类图详解_关联关系_多对一

    首先先来明确一个概念,即多重性.什么是多重性呢?多重性是指两个对象之间的链接数目,表示法是“下限...上限”,最小数据为零(0),最大数目为没有设限(*),如果仅标示一个数目级上下限相同. 实际在UM ...

  8. c3p0-config.xml模板详解

    c3p0-config.xml模板详解 <c3p0-config> <default-config> <!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数.De ...

  9. Android中Application类的详解:

    Android中Application类的详解: 我们在平时的开发中,有时候可能会须要一些全局数据.来让应用中的全部Activity和View都能訪问到.大家在遇到这样的情况时,可能首先会想到自定义一 ...

随机推荐

  1. __FILE__,__LINE__,__DATE__,__TIME__,__FUNCTION__的使用

    C/C++ 有5个常用的预定义宏,可以当作变量直接使用 __FILE__,__FUNCTION __,__LINE__,__DATE__,__TIME__. 注意是两个下划线. 其含义如下: __FI ...

  2. 洛谷$P4768\ [NOI2018]$归程 $kruscal$重构树

    正解:$kruscal$重构树 解题报告: 传送门$QwQ$ 语文不好选手没有人权$TT$连题目都看不懂真的要哭了$kk$ 所以先放个题目大意?就说给定一个$n$个点,$m$条边的图,每条边有长度和海 ...

  3. idea2020注册码永久激活(激活到2100年)

    首先有图有真相: 资源链接: 链接:https://pan.baidu.com/s/1DPIllnyhc7H4qL2yQb0OvQ 提取码:lbjx 第一步:将bin目录下的三个文件拷贝到IDEA安装 ...

  4. Spring事务失效的 8 大原因,这次可以吊打面试官了!

    今天再来一篇<吊打面试官>系列,这次真的要吊打了,哈哈!(看往期吊打系列请在后台回复:吊打,我会陆续更新--) 前几天栈长不是发了一篇文章,里面有一个关于事务失效的问题: 用 Spring ...

  5. Ant Design框架中不同的组件访问不同的models中的数据

    Ant Design框架中不同的组件访问不同的models中的数据 本文记录了我在使用该框架的时候踩过的坑,方便以后查阅. 一.models绑定 在某个组件(控件或是页面),要想从某个models中获 ...

  6. Linux环境下部署svn服务详解

    说明 环境: 操作系统:centos 8.0 IP:39.100.228.13 安装 用ROOT账号登录,在控制台执行以下命令,一直默认安装就好可以了. [root@localhost ~]#yum ...

  7. BZOJ 2038: [2009国家集训队]小Z的袜子 (莫队)

    题目传送门:小Z的袜子 Description 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿.终于有一天,小Z再也无法忍受这恼人的找袜子过程,于是他决定听天由命…… ...

  8. java架构之路(多线程)大厂方式手写单例模式

    上期回顾: 上次博客我们说了我们的volatile关键字,我们知道volatile可以保证我们变量被修改马上刷回主存,并且可以有效的防止指令重排序,思想就是加了我们的内存屏障,再后面的多线程博客里还有 ...

  9. Java 数据结构快速入门

    数据结构:栈 简介 栈(stack),又称堆栈,它是运算受限的线性表. 限制 栈(stack)的限制是仅允许在标的一端进行插入和删除操作,不允许在其他任何位置进行添加.查找.删除等操作. 采用该结构的 ...

  10. 关于SpringDataJpa中测试出现StackOverflowError错误问题

    在使用SpringDataJpa进行多表查询时,使用导航查询,每次都出现 StackOverflowError错误, 经过查找资料,网上百度,终于找到原因, StackOverflowError 是栈 ...