以下是严格保持原文内容(包括所有细节)的Markdown格式重排版,未删减任何文字:
第10章 迭代器模式
10.1 容器和迭代器的简单范例
读者对C++标准库中的容器,例如vector
、list
等都非常熟悉。首先举个例子分别演示一下vector
和list
容器及相关迭代器的使用。为演示方便,首先在MyProject.cpp
的最上面包含两个必需的C++标准库提供的头文件:
#include <vector>
#include <list>
在main
主函数中加入如下代码:
std::vector<int> msgVector;
msgVector.push_back(1); // 末尾插入1,vector中内容:1
msgVector.push_back(2); // 末尾插入2,vector中内容:1,2
msgVector.push_back(3); // 末尾插入3,vector中内容:1,2,3for (std::vector<int>::iterator pos = msgVector.begin(); pos != msgVector.end(); ++pos) {cout << *pos << endl;
}cout << "-------------------" << endl;std::list<int> msgList;
msgList.push_back(1); // 末尾插入1,list中内容:1
msgList.push_front(2); // 开头插入2,list中内容:2,1
msgList.push_back(3); // 末尾插入3,list中内容:2,1,3for (std::list<int>::iterator pos = msgList.begin(); pos != msgList.end(); ++pos) {cout << *pos << endl;
}
执行起来,看一看结果:
1
2
3
-------------------
2
1
3
上面范例演示了vector
、list
容器及其相关迭代器的使用。迭代器是用来遍历容器中的元素的,迭代器模式也正是用来设计和书写迭代器的。
10.2 单一职责原则
10.2.1 单一职责原则的定义
引入面向对象程序设计的一个原则——单一职责原则(Single Responsibility Principle, SRP),它是这样解释的:一个类应该只有一个引起变化的原因,通俗地说,就是一个类的职责应该单一,应该只做一类事情或者对外只提供一种功能。
10.2.2 内聚与耦合
内聚性用于衡量一个模块(或类)内部各组成部分之间彼此结合紧密程度,是指从功能角度来度量模块内的联系。当一个模块被设计成只支持一组相关功能时,就称它具有高内聚;反之,称为低内聚。
耦合性是指模块间相互关联的程度,由高到低排列如下:
-
内容耦合
一个模块直接修改另一个模块的数据或不通过正常入口转入另一个模块。耦合程度最高,应避免。 -
公共耦合
多个模块共同引用全局数据项(如全局变量、共享内存)。 -
外部耦合
模块访问同一全局简单变量(非数据结构),且不通过参数传递。 -
控制耦合
模块通过传递控制信号(如开关、标志)控制另一模块的功能。 -
标记耦合
模块间传递数据结构的地址(如数组名、记录名)。 -
数据耦合
模块间通过参数传递数据,耦合程度最低,推荐使用。
设计原则:高内聚、低耦合(如图10.1)。
10.3 迭代器模式的范例及现代C++中的迭代器
10.3.1 迭代器模式范例
抽象迭代器类模板
template<typename T>
class myIter {
public:virtual void First() = 0; // 指向容器中第一个元素virtual void Next() = 0; // 指向下一个元素virtual bool IsDone() = 0; // 是否遍历完所有元素virtual T& CurrentItem() = 0; // 获取当前元素virtual ~myIter() {} // 作为父类时析构函数应为虚函数
};
抽象容器类模板
template<typename T>
class myContainer {
public:virtual myIter<T>* CreateIterator() = 0; // 创建迭代器(工厂方法)virtual T& getItem(int index) = 0; // 获取指定索引的元素virtual int getSize() = 0; // 获取容器元素数量virtual ~myContainer() {} // 虚析构函数
};
具体迭代器类模板
template<typename T>
class myVectorIter : public myIter<T> {
public:myVectorIter(myContainer<T>* tmpc) : myvector(tmpc) {m_current = 0; // 初始位置为第一个元素(下标0)}void First() override {m_current = 0; // 重置到第一个元素}void Next() override {m_current++; // 移动到下一个元素}bool IsDone() override {return m_current >= myvector->getSize(); // 判断是否越界}T& CurrentItem() override {return myvector->getItem(m_current); // 获取当前元素}private:myContainer<T>* myvector; // 指向容器的指针int m_current; // 当前遍历位置(数组下标)
};
具体容器类模板
template<typename T>
class myVector : public myContainer<T> {
public:myVector() {// 初始化固定大小为10的数组for (int i = 0; i < 10; ++i) {m_elem[i] = i;}}myIter<T>* CreateIterator() override {// 使用工厂模式创建具体迭代器return new myVectorIter<T>(this); // 注意内存释放问题}T& getItem(int index) override {return m_elem[index]; // 返回指定下标的元素}int getSize() override {return 10; // 固定容器大小为10}private:T m_elem[10]; // 容器内部使用固定大小数组
};
main函数测试代码
int main() {myContainer<int>* pcontainer = new myVector<int>();myIter<int>* iter = pcontainer->CreateIterator();// 多态遍历(动态绑定,效率较低)for (iter->First(); !iter->IsDone(); iter->Next()) {cout << iter->CurrentItem() << endl;}cout << "-------------------" << endl;// 非多态遍历(直接栈分配,效率更高)myVectorIter<int> iter2(pcontainer);for (iter2.First(); !iter2.IsDone(); iter2.Next()) {cout << iter2.CurrentItem() << endl;}// 释放资源delete iter;delete pcontainer;return 0;
}
执行结果:
0
1
2
3
4
5
6
7
8
9
-------------------
0
1
2
3
4
5
6
7
8
9
10.3.2 现代C++中的迭代器
C++标准库的迭代器设计不使用动态多态,而是基于模板的编译时多态,效率更高。其核心特点:
- 容器与迭代器解耦:不同容器(如
vector
、list
、map
)提供统一遍历接口 - 迭代器分类:
- 输入迭代器:只读,单遍扫描,++操作
- 输出迭代器:只写,单遍扫描,++操作
- 前向迭代器:读写,多遍扫描
- 双向迭代器:支持–操作(如
list
的迭代器) - 随机访问迭代器:支持
+=
、-=
、[]
等操作(如vector
的迭代器)
迭代器模式UML图
角色说明:
-
Iterator(抽象迭代器)
定义遍历接口(myIter
) -
ConcreteIterator(具体迭代器)
实现具体遍历逻辑(myVectorIter
) -
Aggregate(抽象聚合)
声明迭代器工厂方法(myContainer
) -
ConcreteAggregate(具体聚合)
实现迭代器创建(myVector
)
注意:本章代码为教学示例,实际C++开发应直接使用标准库迭代器(如vector::iterator
)。