本文将继续学习容器的特性:容器元素的关联性和容器元素的索引。
一、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>
上述定义的类Association就是一个键值对,类似于std::map中的std::pair。它有两个成员——key and value,它们都是指针。因此,类Association采用的是简介容器的实现方式。
<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>
注:这里定义了一个“转移Visitor”,它可以将一个容器的元素复制到另一容器,用到了插入操作。
<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>
注:这里展示了两种方法来实现SearchableContainer的接口。它既可以使用Visitor,也可以使用Iterator。
<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>