本文将继续学习容器的特性:容器元素的关联性和容器元素的索引。
一、Associations(点击打开链接)
An association is an ordered pair of objects. The first element of the pair is called the key ; the second element is the value associated with the given key.
关联容器中存储的元素是有序对(键值对,key-value),典型的代表是std::map;非关联容器中的元素则没有键值对的区别,如stack、queue等。
<span style="font-size:14px;">#pragma once #include "Object.h" #include "OwnerShip.h" class Association : public Object, public OwnerShip { public: Association(Object &); Association(Object &, Object &); ~Association(); Object & Key() const; Object & Value() const; //std::hash<Object> Hash() const; void Put(std::ostream &)const; protected: int CompareTo(Object const &) const; Object * key; Object * value; };</span>
<span style="font-size:14px;">#include "stdafx.h" #include "Association.h" #include "NullObject.h" Association::Association(Object & _key) : key(&_key) , value(NULL) { } Association::Association(Object & _key, Object & _value) : key(&_key) , value(&_value) { } Association::~Association() { if (IsOwner()) { delete key; key = NULL; delete value; value = NULL; } } Object & Association::Key() const { return *key; } Object & Association::Value() const { if (value == 0) return NullObject::Instance(); else return *value; } int Association::CompareTo(Object const & object) const { Association const & association = dynamic_cast<Association const &> (object); return Key().Compare(association.Key()); } void Association::Put(std::ostream & s) const { s << "Association { " << *key; if (value != NULL) s << ", " << *value; s << " }"; } </span>
二、Searchable Container
在介绍完前面几篇的内容后,现在可以来探讨容器的元素操作:添加、删除、索引等。Searchable Container就是对基础抽象容器的功能扩展,增加了如下四个接口:
<span style="font-size:14px;">class SearchableContainer : public virtual Container { public: virtual bool IsMemeber(Object const &) const = 0; virtual void Insert(Object &) = 0; virtual void Withdraw(Object &) = 0; virtual Object & Find(Object const &) const = 0; };</span>
这四个接口分别代表四个功能,即“It adds to the interface provided for containers functions for putting objects in and taking objects out, for testing whether a given object is in the container, and a routine to search the container for a given object.”
需要注意的是,该容器是指针容器,“Find”的语义是找相等值,然后从容器中返回值相等的Object。此外,“Insert”函数没有指定位置,目前来说,容器还没有位置的概念,后面讲到具体的数据结构的时候会定义位置的概念。
下面展示全部代码和一个具体的类。
<span style="font-size:14px;">#pragma once #include "Container.h" class SearchableContainer : public virtual Container { public: virtual bool IsMemeber(Object const &) const = 0; virtual void Insert(Object &) = 0; virtual void Withdraw(Object &) = 0; virtual Object & Find(Object const &) const = 0; }; class TransferingVisitor : public Visitor { public: TransferingVisitor(SearchableContainer & container) : destination(container) {} void Visit(Object & object) { destination.Insert(object); } private: SearchableContainer & destination; };</span>
<span style="font-size:14px;">#include "stdafx.h" #include "SearchableContainer.h" #include "NullObject.h" #include <algorithm> //Methods of class SearchableContainer bool SearchableContainer::IsMemeber(Object const & object) const { MatchingVisitor visitor(object); this->Accept(visitor); return visitor.IsDone(); } Object & SearchableContainer::Find(Object const & object) const { //MatchingVisitor visitor(object); //this->Accept(visitor); //// visitor.Found(); //return NullObject::Instance(); Iterator & iter = this->NewIterator(); while (!iter.IsDone()) { if (*iter == object) break; ++iter; } return *iter; } </span>
<span style="font-size:14px;">#pragma once #include "SearchableContainer.h" #include "DynamicArray.h" #include "Wrapper.h" using namespace FoundationalDataStructure; typedef Wrapper<char> SomeObject; class Bag : public SearchableContainer { public: class BagIterator : public Iterator { public: BagIterator(Object *& ptr) : _ptr(ptr){} BagIterator(BagIterator& iter) : _ptr(&*iter){} BagIterator& operator = (BagIterator& iter) { _ptr = &*iter; } void Reset() { _ptr = NULL; } bool IsDone() const { return _ptr == NULL; } Object& operator * () const { return *_ptr; } void operator ++() { ++_ptr; } private: Object* _ptr; }; Bag(); ~Bag(); Iterator & NewIterator() const; void Purge(); void Accept(Visitor &) const; bool IsMemeber(Object const &) const; void Insert(Object &); void Withdraw(Object &); Object & Find(Object const &) const; protected: int CompareTo(Object const &) const; private: Array<SomeObject> array; //Array<Object> array; }; </span>
<span style="font-size:14px;">#include "stdafx.h" #include "bag.h" Bag::Bag() { } Bag::~Bag() { Purge(); } Iterator & Bag::NewIterator() const { Object * pObject = dynamic_cast<Object*>(const_cast<SomeObject*>(array.Data())); return *(new BagIterator(pObject)); } void Bag::Purge() { if (IsEmpty()) return; if (IsOwner()) { SomeObject* pObject = const_cast<SomeObject*>(array.Data()); delete pObject; pObject = NULL; } else { for (unsigned int i = 0; i < array.Length(); ++i) { Withdraw(array[i]); } } count = 0; } void Bag::Accept(Visitor & visitor) const { for (unsigned int i = 0; i < array.Length(); ++i) { if (visitor.IsDone()) return; Object * pObject = dynamic_cast<Object*>(const_cast<SomeObject*>(&array[i])); visitor.Visit(*pObject); } } bool Bag::IsMemeber(Object const & object) const { return SearchableContainer::IsMemeber(object); } void Bag::Insert(Object & object) { unsigned int length = array.Length(); array.SetLength(length + 1); array[length] = *dynamic_cast<SomeObject*>(&object); } void Bag::Withdraw(Object & object) { Array<SomeObject> newArray; newArray.SetLength(array.Length() - 1); for (unsigned int i = 0; i < array.Length(); ++i) { if (array[i] == object) break; newArray[i] = array[i]; } array = newArray; } Object & Bag::Find(Object const & object) const { return SearchableContainer::Find(object); } int Bag::CompareTo(Object const & object) const { Bag const & bag = dynamic_cast<Bag const &> (object); return 0; } </span>