抽象数据类型之容器(一)
来源:互联网 发布:gre知乎 编辑:程序博客网 时间:2024/06/04 07:29
本系列文章基于我之前的“抽象数据类型与类层次”系列,专门讲解“抽象容器”及其相关概念。(点击打开链接)
一、容器类
根据上面的类层次图,容器也是一种“Object”。容器是一种能够存储其他物体的物体。下面使用一个容器类来抽象容器这个概念。
<span style="font-size:14px;">#pragma once#include "Object.h"#include "OwnerShip.h"#include "Visitor.h"#include "Iterator.h"class Container : public virtual Object, public virtual OwnerShip{public: virtual unsigned int Count() const; virtual bool IsEmpty() const; virtual bool IsFull() const; //virtual std::hash<Object> Hash() const; virtual void Put(std::ostream &)const; virtual Iterator & NewIterator() const; virtual void Purge() = 0; virtual void Accept(Visitor &) const = 0;protected: Container(); unsigned int count;};</span>
注:容器类是一种抽象类,并不产生实际的具体对象,故其构造函数可以是“Protercted”。
<span style="font-size:14px;">#include "stdafx.h"#include "Container.h"#include "NullIterator.h"#include <typeinfo>Container::Container() : count(0){}unsigned int Container::Count() const{ return count;}bool Container::IsEmpty() const{ return Count() == 0;}bool Container::IsFull() const{ return false;}void Container::Put(std::ostream & s) const{ PuttingVisitor visitor(s); s << typeid(*this).name() << " {"; Accept(visitor); s << "}";}Iterator & Container::NewIterator() const{ return *new NullIterator();}</span>
注:“IsEmpty函数”中使用的不是成员变量来直接判断,是因为考虑到容器的子类对计数或空容器的判断方法可能重载。
二、Visitor类
在上面容器类中,有一个“Accept接口函数”,该函数需要一个Vistitor类引用作为参数。这个接口用到的就是Visitor Pattern(访问者模式)。
<span style="font-size:14px;">class Visitor{public: virtual void Visit(Object &) = 0; virtual bool IsDone() const { return false; }};</span>
Visitor类其实非常简单,它只有两个接口函数,其中“Visit函数”接受一个Object引用为参数,对该Object对象进行某些处理。因此,Visitor与Container有一个交互,这个交互过程是这样的:Container通过调用Accept函数接受一个Visitor,即接受一种算法或处理方式,然后遍历Container的各个元素,将元素逐个传递给Visitor,对他们逐个进行Visit操作(算法)。这其实也是一种将算法与待处理对象分离的设计方法。
<span style="font-size:14px;">void SomeContainer::Accept (Visitor& visitor) const for each Object i in this container if (visitor.IsDone ()) return; visitor.Visit (i);</span>
<span style="font-size:14px;"><span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"> Visitor类的另一个函数“IsDone”可以作为“Accept函数”中的循环中断条件。</span></span>
<span style="font-size:14px;"><span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"> 下面再展示几个具体的Visitor类和全部代码:</span></span>
<span style="font-size:14px;">#ifndef VISITOR_H#define VISITOR_H#include "Object.h"#include <ostream>class Visitor{public: virtual void Visit(Object &) = 0; virtual bool IsDone() const { return false; }};class PuttingVisitor : public Visitor{public: PuttingVisitor(std::ostream & s) : stream(s), comma(false) {} void Visit(Object & object) { if (comma) stream << ", "; stream << object; comma = true; }private: std::ostream & stream; bool comma;};class MatchingVisitor : public Visitor{public: MatchingVisitor(Object const & object) : target(object), found(NULL) {} void Visit(Object & object) { if (found == NULL && object == target) found = &object; } bool IsDone() const { return found != NULL; }private: Object const & target; Object * found;};#endif // VISITOR_H</span>
返回Container的实现代码看“Put函数”,它里面也用到了一种Visitor。实际上,Visitor是对操作(算法)的一种抽象,不针对具体对象,故它可以用于Accept函数,也可用在其他地方,提高代码复用。这就是Visitor Pattern的优势。
三、Visitor类与仿函数
先看“PuttingVisitor”,它的功能其实可以用一个函数指针来代替。设计一个函数指针,它接受一个Object &参数。再看“MatchingVisitor”,它的功能其实也可以用一个函数对象来代替,只需要在这个函数对象构造的时候给它传递一个参数。此外,使用C++11中的std::function(函数对象包装器)和std::bind,可以将这种设计变得更通用化。
0 0
- 抽象数据类型之容器(一)
- 抽象数据类型之容器(二)
- 抽象数据类型之容器(三)
- 抽象数据类型之容器(四)
- 基础算法(一)---抽象数据类型之表
- 抽象数据类型(ADT)入门(一)
- 抽象数据类型与类层次(一)
- 第十七章经典抽象数据类型(一)
- 基础算法(一)---抽象数据类型之栈(先进后出)
- 基础算法(一)---抽象数据类型之队列(先进先出)
- 抽象数据类型之表(List)
- 数据结构之抽象数据类型
- 数据结构(一) 抽象数据类型的表示与实现
- 抽象数据类型之表(不断更新)
- 菜鸟笔记之抽象数据类型
- 抽象数据类型(链表)
- 列表(抽象数据类型)
- python之Collections容器数据类型
- mysql 删除重复数据只保留一条sql
- 深入分析JavaWeb 9 -- HttpServletRequset详解
- mingw的安装
- Android学习笔记之四大组件篇--->Activity
- 子父间的成员变量关系:就近原则
- 抽象数据类型之容器(一)
- BSOJ4548:陌上花开 树状数组套平衡树(基础题)
- 【代码笔记】iOS-scrollerView里多个tableView加搜索框
- python中文编码问题(转自http://wolfmaster.iteye.com/blog/638029)
- C++异常
- Fragment 入门
- PIC18F45K80 CAN通讯示例代码
- MTK SPI总线简单介绍及驱动示例
- Android中scrollTo()和scrollBy()的区别以及Scroller源码解析