8、泛型程序设计与c++标准模板库1、泛型程序设计的概念和术语
有效地利用已有的成果,将经典的、优秀的算法标准化、模块化,从而提高软件的生产率,是软件产业化的需求,为了实现这一需求,不仅需要面向对象设计思想,而且需要泛型程序设计思想。
c++语言提供的标准模板库(standard template library,STL)便是对象对象程序设计和泛型程序设计(Generic Programming)思想相结合的一个良好典范。
1、泛型程序设计的概念和术语
1)泛型程序设计
泛型程序设计就是要将程序写得尽可能通用,同时并不损失效率。它的首要目标是标准容器,进而是标准算法,总的目标是最通用、最有效最灵活地表现概念。
标准c++类库包含的组建即支持面向对象的设计与编程,又支持泛型程序设计。标准组件对来年各种设计方法的支持赋予了c++类库复合或双重特性。c++的模板为泛型程序设计奠定了关键的基础,它是所有版本STL的基石。
泛型程序设计的主要思想是,将算法从特定的数据结构中抽象出来,使算法成为通用的,可以作用于各种不同的数据结构。这种以函数模板形式实现的通用算法与各种通用容器结合,极大地提高了软件的复用性。
在STL中充当苏纳法与容器之间媒介的,便是迭代器(iterator)。
如果从应用角度来看,构建STL的架构最关键的4个组件是容器、迭代器、算法和函数对象。算法处于核心地位,迭代器如同算法和容器类之间的桥梁,算法通过迭代器从容器中获取元素,然后将获取的元素传递给特定的函数对象进行的操作,最后将处理后的结果存储到容器中。
2)命名空间的概念
一个命名空间将不同标识符集合在一个命名作用域内。为了说明标识符属于哪一个命名空间的,需要在标识符前面加上命名空间名字和“::”,例如,如下形式声明一个命名空间NS,并在其中声明若干标识符:
namespace NS{
class File;
void Fun();
}
则引用标识符的方式如下:
NS::File obj;
NS::Fun();
除了这样声明的命名空间外,还有一个无名的命名空间,无需特殊声明。在声明标识符时并未指定命名空间,这些标识符便属于无名的命名空间。
为了避免总是在标识符前面写很长的前缀,可以用using来指定命名空间。如经过以下声明
using NS::File;
在当前作用域中就可以直接引用标识符File,也就是说File与NS::File等效。
如果使用声明Using namespace NS;NS命名空间中的所有标识符在当前作用域中都可以直接使用,无需任何前缀。但这样的命名冲突问题又来了。。。
在c++标准程序中,使用了命名空间std,在使用c++标准程序库的任何标识符时,可以直接指定标识符所属的命名空间。如std::out,也可以使用using来打开命名空间的限制。
3)头文件命名规则
在新的c++标准程序库中,所有标识符都声明在命名空间std中,而且头文件都不使用扩展名,(#include<iostream>与#Include<iostream.h>等价)
为了使用STL中的组件,必须使用#Include命令以包含一个或多个头文件:
1)向量容器、列表容器和双端队列容器类分别位于<vector>、<list>、和<deque>中。
2)集合容器和多重集合容器位于<set>中,而映射容器map和多重映射容器multimap位于<map>。
3)stack适配器位于<stack>中,而queue和priority_queue适配器位于<queue>中。
4)算法位于<algorithm>中,通用数值算法位于<numeric>中。
5)迭代器类和迭代器适配器位于<iterator>中。
6)函数对象类和函数适配器位于<functional>中。
4)标准模板库相关概念和术语
1、容器
容器类是容纳、包含一组元素或元素集合的对象。容器类中包含一组元素或一个元素集合,作为通用元素收集器。c++语言的容器类中可以包含混合类型的元素,即容器类可以包含一组不同类型的元素或一组相同类型的元素。当容器类包含不同类型的元素时,称为异类容器类;当容器类包含相同类型的元素时,称为同类容器类。
容器类库中包括7种基本容器:向量(vector)、双端队列(deque)、列表(list)、集合(set)、多重集合(multiset)、映射(map)和多重映射(multimap)等。这7种容器可以分为2中基本类型:顺序容器和关联容器。
顺序容器将一组具有相同类型的元素以严格的线性形式组织起来,向量、双端队列和列表容器就属于这一种。关联容器具有根据一组索引来快速提取元素的能力,集合和映射容器就属于这一种。
2、适配器
适配器是一种接口类,为已有的类提供新的接口。适配器修改或调整其他类的接口,目前是简化、约束、使之安全、隐藏或者改变被修改类提供的服务集合。
当某个类使用的唯一目的就是改变其他类的接口形式时,它就是一个适配器或一个接口类。
c++标准模板库提供了3种类型的适配器:容器适配器、迭代器适配器和函数对象适配器。其中容器适配器来扩展7种基本容器,他们和顺序容器相结合构成栈、队列和优先队列容器,提供了栈、队列和优先队列的功能。
3、迭代器
迭代器是面向对象版本的指针,他们提供了访问容器和序列中每个元素的方法。实际上指针也是一种迭代器。很多容器和序列提供了类似于current()的成员函数,返回迭代其所指向的元素的地址或引用。类似于指针,迭代器可以调用next()和previous()等成员函数顺序遍历容器。
4、算法
c++标准模板库中包括70多个算法,这些算法覆盖了相当大的应用领域。其中包括查找算法、排序算法、消除算法、记数算法、比较算法、变换算法、置换算法和容器管理等等,这些算法的一个最重要的特性就是他们的统一性,并且可以广泛应用于不同的对象和内置的数据类型。
5、容器的接口
在有效使用容器之前,理解容器类的接口是非常重要的。所谓的“接口”是指容器的方法(函数)和运算符。
每个容器包括一个或多个公有的构造、拷贝构造、析构函数。除此之外,所有的容器都支持一个运算符集合,这些运算符完成字典式的比较。
所有标准容器定义的运算符
通用容器运算符 说明
a==b 同类容器的等于操作
a!=b 同类容器的不等于操作,和!(a==b)等价
a>b 如果b<a,返回布尔型true
a>=b 如果!(a<b),返回布尔型true
a<b 如果a<b,返回布尔型true
a<=b 如果!(b<a),返回布尔型true
r=a 容器的赋值操作,需要有r==a
注:假设有一容器类x,这里a和b是x的实例,r是类型x&的值。
所有的容器至少有4中迭代方法和4种访问方法,4种迭代方法用来访问容器中的元素,4种访问方法用来访问容器信息。
每种容器定义的迭代和访问方法
迭代方法 说明
begin() 返回一个指向容器的第一个元素的迭代器(iterator)
end() 返回一个指向容器末尾值的迭代器
rbegin() 返回reverse_iterator(end()),一个逆向迭代器,指向反序后的首元素
rend() 返回reverse_iterator *(begin()),一个逆向迭代器,指向反序后的尾元素。
访问方法 说明
size() 返回容器的元素数
max_size() 返回容器可以容纳的最大元素数
swap() 交换两个相同类型的容器
empty() 如果容器为空或者size()=0,则返回真(true)。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】