前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >【C++】模拟实现reverse_iterator(反向迭代器适配器)

【C++】模拟实现reverse_iterator(反向迭代器适配器)

作者头像
修修修也
发布2024-08-11 08:34:20
发布2024-08-11 08:34:20
8500
代码可运行
举报
运行总次数:0
代码可运行

一.了解项目功能

📌什么是适配器

适配器是一种设计模式(设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结),该种模式是将一个类的接口转换成客户希望的另外一个接口 :

📌了解reverse_iterator官方标准

在本次项目中我们的目标是模拟实现一个reverse_iterator,先一起看一下C++标准文档中reverse_iterator的定义:cplusplus : C++ reverse_iterator标准文档

https://legacy.cplusplus.com/reference/iterator/reverse_iterator/?kw=reverse_iterator

反向迭代器示意图:

如果对正向迭代器的实现还不太了解的朋友可以先移步下面这篇文章的第三部分,文章以List迭代器为例,手把手教大家如何构建迭代器类模板,这部分是逆向迭代器实现的基础:【C++】模拟实现list

https://blog.csdn.net/weixin_72357342/article/details/140809635?spm=1001.2014.3001.5501


📌了解模拟实现reverse_iterator

在本次项目中我们的目标是实现一个reverse_iterator(反向迭代器适配器):reverse_iterator适配器底层是使用iterator来实现的. reverse_iterator提供的功能有:

  1. reverse_iterator构造函数
  2. operator++函数重载
  3. operator++(int)函数重载
  4. operator--函数重载
  5. operator--(int)函数重载
  6. operator*函数重载
  7. operator->函数重载
  8. operator!=函数重载
  9. operator==函数重载

二.逐步实现项目功能模块及其逻辑详解

通过第一部分对项目功能的介绍,我们已经对reverse_iterator的功能有了大致的了解,虽然看似需要实现的功能很多,貌似一时间不知该如何下手,但我们可以分步分模块来分析这个项目的流程,最后再将各部分进行整合,所以大家不用担心,跟着我一步一步分析吧!

!!!注意,该部分的代码只是为了详细介绍某一部分的项目实现逻辑,故可能会删减一些与该部分不相关的代码以便大家理解,需要查看或拷贝完整详细代码的朋友可以移步本文第三部分。

📌实现reverse_iterator成员变量

因为reverse_iterator的底层是用iterator来实现的,所以我们只需要定义一个iterator成员变量即可.但因为我们选择将reverse_iterator写成类模板,所以这里成员变量的类型是模板类型.

其实可以理解为reverse_iterator的底层就是一个iterator,但我们通过类的特性,对iterator进行进一步的封装,使其行为符合reverse_iterator的行为,就完成了一个reverse_iterator类模板.

注意,为了使迭代器成员及其函数可以直接被其他类使用,我们将其设为struct类.

代码如下:

代码语言:javascript
代码运行次数:0
复制
namespace mfc
{
	template<class Iterator, class Ref, class Ptr>
	struct reverse_iterator
	{
		typedef reverse_iterator<Iterator, Ref, Ptr> self;    //重定义缩短一下
		Iterator _it;        //成员变量

	};
}

📌实现reverse_iterator()构造函数

构造函数很简单,就是用初始化列表把传入的iterator参数it赋值给_it即可,代码如下:

代码语言:javascript
代码运行次数:0
复制
reverse_iterator(Iterator it)
	:_it(it)
{}

📌实现operator++函数重载

因为是逆向遍历,reverse_iterator的++操作其实是底层iterator的--操作,我们直接调用iterator的函数接口即可,前置++返回++后的结果,所以我们操作完直接返回*this指针即可,代码如下:

代码语言:javascript
代码运行次数:0
复制
self operator++()
{
	--_it;
	return *this;
}

📌实现operator++(int)函数重载

因为是逆向遍历,reverse_iterator的++操作其实是iterator的--操作,我们直接调用iterator的函数接口即可,后置++要返回++前的结果,所以我们要提前设一个变量来记录++前的值,操作完直接返回该变量即可,代码如下:

代码语言:javascript
代码运行次数:0
复制
self operator++(int)
{
	Iterator tmp = _it;
	--_it;
	return tmp;
}

📌实现operator--函数重载

因为是逆向遍历,reverse_iterator的--操作其实是iterator的++操作,我们直接调用iterator的函数接口即可,前置--返回--后的结果,所以我们操作完直接返回*this指针即可,代码如下:

代码语言:javascript
代码运行次数:0
复制
self operator--()
{
	++_it;
	return *this;
}

📌实现operator--(int)函数重载

因为是逆向遍历,reverse_iterator的--操作其实是iterator的++操作,我们直接调用iterator的函数接口即可,后置--要返回--前的结果,所以我们要提前设一个变量来记录--前的值,操作完直接返回该变量即可,代码如下:

代码语言:javascript
代码运行次数:0
复制
self operator--(int)
{
	Iterator tmp = _it;
	++_it;
	return tmp;
}

📌实现operator*函数重载

因为我们在设计迭代器时是仿照STL源码对称设计的,所以我们的反向迭代器其实是指向对应结点的后一个位置的:

那么正常情况下我们想要获得当前指针的值,就要去解引用该指针前一个位置的值,要解引用前一个位置,可以直接调底层iterator的*和--函数,注意*操作_it不能改变,所以我们创建一个变量tmp代替_it--,代码如下:

代码语言:javascript
代码运行次数:0
复制
Ref operator*()
{
	Iterator tmp = _it;//解引用不动当前数据,但是要返回前一个数据的解引用,只有用一个变量来代替--了
	return *(--tmp);
}

📌实现operator->函数重载

operator->操作就是获得迭代器指向的成员变量的地址,那我们可以直接调用解引用操作再取地址,代码如下:

代码语言:javascript
代码运行次数:0
复制
Ptr operator->()
{
	return &(operator*());
}

📌实现operator!=函数重载

判断迭代器不相等底层iterator类模板里已经支持了,我们直接调用即可,代码如下:

代码语言:javascript
代码运行次数:0
复制
bool operator!=(const self& s) const
{
	return _it != s._it;
}

📌实现operator==函数重载

判断迭代器相等底层iterator类模板里已经支持了,我们直接调用即可,代码如下:

代码语言:javascript
代码运行次数:0
复制
bool operator==(const self& s) const
{
	return _it == s._it;
}

三.项目完整代码

因为模板定义和声明不能分离,所以我们将程序运行的代码分别在一个工程文件中编辑,完整代码如下:

📌ReverseIterator.h文件

代码语言:javascript
代码运行次数:0
复制
namespace mfc
{
	template<class Iterator, class Ref, class Ptr>
	struct reverse_iterator
	{
		typedef reverse_iterator<Iterator, Ref, Ptr> self;
		Iterator _it;

		reverse_iterator(Iterator it)
			:_it(it)
		{}
		self operator++()
		{
			--_it;
			return *this;
		}
		self operator++(int)
		{
			Iterator tmp = _it;
			--_it;
			return tmp;
		}
		self operator--()
		{
			++_it;
			return *this;
		}
		self operator--(int)
		{
			Iterator tmp = _it;
			++_it;
			return tmp;
		}
		Ref operator*()
		{
			Iterator tmp = _it;//解引用不动当前数据,但是要返回前一个数据的解引用,只有用一个变量来代替--了
			return *(--tmp);
		}
		Ptr operator->()
		{
			return &(operator*());
		}
		bool operator!=(const self& s) const
		{
			return _it != s._it;
		}
		bool operator==(const self& s) const
		{
			return _it == s._it;
		}
	};
}

结语

希望这篇reverse_iterator的模拟实现详解能对大家有所帮助,欢迎大佬们留言或私信与我交流.

学海漫浩浩,我亦苦作舟!关注我,大家一起学习,一起进步!

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-08-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一.了解项目功能
    • 📌什么是适配器
    • 📌了解reverse_iterator官方标准
    • 📌了解模拟实现reverse_iterator
  • 二.逐步实现项目功能模块及其逻辑详解
    • 📌实现reverse_iterator成员变量
    • 📌实现reverse_iterator()构造函数
    • 📌实现operator++函数重载
    • 📌实现operator++(int)函数重载
    • 📌实现operator--函数重载
    • 📌实现operator--(int)函数重载
    • 📌实现operator*函数重载
    • 📌实现operator->函数重载
    • 📌实现operator!=函数重载
    • 📌实现operator==函数重载
  • 三.项目完整代码
    • 📌ReverseIterator.h文件
  • 结语
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档