C++ Templates (2.1 类模板Stack的实现 Implementation of Class Template Stack)
2.1 类模板Stack的实现 Implementation of Class Template Stack
正如函数模板,可以如下方式在一个头文件中声明和定义类Stack<>:
// basics/stack1.hpp
#include <vector>
#include <cassert>
template <typename T>
class Stack
{
private:
std::vector<T> elems; //元素
public:
void push(T const& elem); //压入元素
void pop(); // 弹出元素
T const& top() const; //返回顶上的元素
bool empty() //返回栈stack是否为空
{
return elems.empty();
}
};
template <typename T>
void Stack<T>::push(T const& elem)
{
elems.push_back(elem); //将elem的拷贝放入elems末尾
}
template <typename T>
void Stack<T>::pop()
{
assert(!elems.empty());
elems.pop_back(); //移除最后一个元素
}
template <typename T>
T const& Stack<T>::top() const
{
assert(!elems.empty());
return elems.back(); //返回最后一个元素
}
正如所看到的,该类模板使用C++标准库的vector<>实现,这样便无需实现内存管理、拷贝控制和赋值运算,这样便可以将重心放在类模板的接口上。
2.1.1 声明类模板 Declaration of Class Templates
声明类模板与声明函数模板类似:在声明之前,必须声明一个或多个类型参数的标识符。再一次,T是一个常用的标识符:
template <typename T>
class Stack
{
...
};
此处的关键字typename也可以用class代替:
template <class T>
class Stack
{
...
};
在类模板中,T可以像其他任何类型一样用于声明成员和成员函数(member function)。该例子中,T用于声明成员的类型为T的向量vector,用于声明成员函数push()使用T类型作为参数,用于声明成员函数top()的返回类型。
template <typename T>
class Stack
{
private:
std::vector<T> elems; //元素
public:
void push(T const& elem); //压入元素
void pop(); // 弹出元素
T const& top() const; //返回顶上的元素
bool empty() //返回栈stack是否为空
{
return elems.empty();
}
};
该类的类型为Stack,其中T为模板参数。因此,只要在声明中使用该类的类型,必须使用Stack,除非模板参数可以推断而得。然而,在类模板内,使用没有模板实参的类名意味着将类模板实参作为模板参数(However, inside a class template using the class name not followed by template arguments represents the class with its template parameters as its arguments.)(详见13.2.3节)。
比如,如果必须声明构造函数和赋值运算符,这通常看起来像这样:
template <typename T>
class Stack
{
...
Stack(Stack const&); //拷贝构造
Stack& operator=(Stack const&); //赋值运算符
};
这与如下形式等价:
template <typename T>
class Stack
{
...
Stack(Stack<T> const&); //拷贝赋值
Stack<T>& operator=(Stack<T> const&); //赋值运算符
};
但通常意味着对特殊模板参数的特殊处理,因此第一种形式更好。
然而,在类结构之外需要指定模板参数:
template <typename T>
bool operator==(Stack<T> const& lhs, Stack<T> const& rhs);
注意到在需要类名而不是类的类型的地方,仅仅使用Stack便可以。这特别是在构造函数和析构函数名字的情形中。
与非模板类不同,不能在函数内部或者块作用域(block scope)内声明类模板。通常,模板只能定义在全局作用域(global scope)或者命名空间作用域(namespace scope)或者类声明内(详见12.1节)。
2.1.2 成员函数实现 Implementation of Member Functions
定义类模板的成员函数必须指定这是一个模板且必须使用类模板的完整类型限制。因此,类型Stack的成员函数push()的实现为
template <typename T>
void Stack<T>::push(T const& elem)
{
elems.push_back(elem); //将elem的拷贝放入elems末尾
}
该情况下,成员向量的push_bask()方法被调用,将元素放入向量vector的末尾。
注意到向量vector的pop_back()将移除最后一个元素但不返回,这行为的原因是异常安全(exception safety)。不可能实现一个返回移除元素的完全异常安全的pop()版本(该问题首先由Tom Cargill在[CargilExceptionSafety]中的第10项条款[SutterExceptional]中讨论)。然而,如果忽略该危险,可以实现返回移除的元素的pop()。为实现此功能,简单地使用T来声明类型为元素类型的局部变量:
template <typename T>
T Stack<T>::pop()
{
assert(!elems.empty());
T elem = elems.back(); //保存最后一个元素
elems.pop_back(); //移除最后一个元素
return elem; //返回保存元素的拷贝
}
由于当vector中没有元素时,back()(返回最后一个元素)和pop_back()(移除最后一个元素)都将有未定义的行为,因此需要检查栈是否为空。如果为空,则断言(assert),因为在空的栈上调用pop()是错误的。在top()上也需要这么做,它返回顶上的元素但不移除:
template <typename T>
T const& Stack<T>::top() const
{
assert(elems.empty());
return elems.back(); //返回最后一个元素
}
当然,对于任何成员函数,也可以将类模板的成员函数在类的声明中实现为inline,比如:
template <typename T>
class Stack
{
...
void push(T const& elem)
{
elems.push_back(elem); //将elem放入末尾
}
};
C++ Templates (2.1 类模板Stack的实现 Implementation of Class Template Stack)的更多相关文章
- c++11-17 模板核心知识(二)—— 类模板
类模板声明.实现与使用 Class Instantiation 使用类模板的部分成员函数 Concept 友元 方式一 方式二 类模板的全特化 类模板的偏特化 多模板参数的偏特化 默认模板参数 Typ ...
- C++解析(26):函数模板与类模板
0.目录 1.函数模板 1.1 函数模板与泛型编程 1.2 多参数函数模板 1.3 函数重载遇上函数模板 2.类模板 2.1 类模板 2.2 多参数类模板与特化 2.3 特化的深度分析 3.小结 1. ...
- 初步C++类模板学习笔记
类模板 实现:在上课时间的定义给它的一个或多个参数,这些参数代表了不同的数据类型. -->抽象的类. 在调用类模板时, 指定參数, 由编 ...
- C++程序设计方法4:类模板
类模板 在定义类时也可以将一些类型抽象出来,用模板参数来替换,从而使类更具有通用性.这种类被称为模板类,例如: template <typename T> class A { T data ...
- C++ 模板学习 函数模板、类模板、迭代器模板
使用模板能够极大到使得代码可重用. 记录一下,方便后续使用. 1. 函数模板,支持多种类型参数 #include <stdio.h> #include <math.h> //函 ...
- C++ 函数模板与类模板(使用 Qt 开发编译环境)
注意:本文中代码均使用 Qt 开发编译环境,如有疑问和建议欢迎随时留言. 模板是 C++ 支持参数化程序设计的工具,通过它可以实现参数多态性.所谓参数多态性,就是将程序所处理的对象的类型参数化,使得一 ...
- C++入门经典-例9.3-类模板,简单类模板
1:使用template关键字不但可以定义函数模板,而且可以定义类模板.类模板代表一族类,它是用来描述通用数据类型或处理方法的机制,它使类中的一些数据成员和成员函数的参数或返回值可以取任意数据类型.类 ...
- C++ Templates (2.2 使用Stack类模板 Use of Class Template Stack )
返回完整目录 目录 2.2 使用Stack类模板 Use of Class Template Stack 2.2 使用Stack类模板 Use of Class Template Stack 在C++ ...
- C++ Templates (2.3 类模板的局部使用 Partial Usage of Class Templates)
返回完整目录 目录 2.3 类模板的局部使用 Partial Usage of Class Templates 2.3.1 Concepts 2.3 类模板的局部使用 Partial Usage of ...
随机推荐
- leetcode题库练习_左旋转字符串
题目:左旋转字符串 字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部.请定义一个函数实现字符串左旋转操作的功能.比如,输入字符串"abcdefg"和数字2,该函数将返 ...
- 全卷积神经网络FCN详解(附带Tensorflow详解代码实现)
一.导论 在图像语义分割领域,困扰了计算机科学家很多年的一个问题则是我们如何才能将我们感兴趣的对象和不感兴趣的对象分别分割开来呢?比如我们有一只小猫的图片,怎样才能够通过计算机自己对图像进行识别达到将 ...
- 一分钟速学 | NMS, IOU 与 SoftMax
非极大抑制 NMS的英文是Non-maximum suppression的缩写. 简单的说,就是模型给出了多个重叠在一起的候选框,我们只需要保留一个就可以了.其他的重叠的候选框就删掉了,效果可见下图: ...
- Python File tell() 方法
概述 tell() 方法返回文件的当前位置,即文件指针当前位置.高佣联盟 www.cgewang.com 语法 tell() 方法语法如下: fileObject.tell() 参数 无 返回值 返回 ...
- PHP gd_info - 取得当前安装的 GD 库的信息
gd_info — 取得当前安装的 GD 库的信息. 语法 array gd_info ( void )高佣联盟 www.cgewang.com 返回一个关联数组描述了安装的 GD 库的版本和性能. ...
- PHP sscanf() 函数
实例 Parse a string: <?php高佣联盟 www.cgewang.com$str = "age:30 weight:60kg";sscanf($str,&qu ...
- CMD使用笔记
CMD杂谈 基本功: 1,列出所有任务及进程号,杀进程 tasklist tasklist /? 获取使用帮助 taskkill taskkill /? 获取使用帮助 2,cd 切换目录 cd ...
- 如何在 Android 安卓手机上运行 Node.js 应用 | 如何在安卓手机配置node开发环境
最近在学习js,由于没法随身携带笔记本电脑,在手机翻阅<JavaScript高级程序设计>时,时常想调试一下书中的代码.于是就有了,能否在手机上配置一个js开发环境.考虑到手机上的Chro ...
- Qt 中十六进制字节流转换为Base64编码
在Qt中,在网络通信时,有时需要将16进制字节流转换为Base64编码传输,在Qt的QByteArray类中,提供了与Base64转换的接口: //16进制字节流转为Base64 QByteArray ...
- Jenkins=====》部署到构建完成
目录 序言 正文 插件 系统管理 构建Maven项目 结尾 序言 大家好,我是龙宝,来自一个正在爬坑的java程序员,欢迎观看这一期的jenkins部署篇(V_V) 正文 这里我们直接上图看步 ...