我目前正在开展一个项目,我想在其中定义一个可以以不同方式实现的通用“集合”界面。集合接口应指定集合具有按值返回迭代器的方法。使用包装指针的类我得到了以下(大大简化):
Collection.h
class Collection
{
CollectionBase *d_base;
public:
Collection(CollectionBase *base);
Iterator begin() const;
};
inline Iterator Collection::begin() const
{
return d_base->begin();
}
CollectionBase.h
class CollectionBase
{
public:
virtual Iterator begin() const = 0;
virtual Iterator end() const = 0;
};
Iterator.h
class Iterator
{
IteratorBase *d_base;
public:
bool operator!=(Iterator const &other) const;
};
inline bool Iterator::operator!=(Iterator const &other) const
{
return d_base->operator!=(*other.d_base);
}
IteratorBase.h
class IteratorBase
{
public:
virtual bool operator!=(IteratorBase const &other) const = 0;
};
使用此设计,集合的不同实现派生自CollectionBase
,并且可以通过返回包含Iterator
的某些特定实现的IteratorBase
来返回其自定义迭代器。
operator!=
。 Iterator
将呼叫转发给IteratorBase
,但如何在那里实施运营商?一种直接的方法是在IteratorBase
的实现中将IteratorBase
引用转换为适当的类型,然后对IteratorBase
的实现执行特定的比较。这假设你会玩得很好而不会传递两种不同类型的迭代器。
另一种方法是执行某种类型的类型检查,检查迭代器是否属于同一类型。我相信这个检查必须在运行时进行,并且考虑到这是一个迭代器,我宁愿不在operator!=
执行昂贵的运行时类型检查。
我在这里错过了任何更好的解决方案吗?也许有更好的替代类设计(目前的设计是我在C ++课程中学到的东西的改编)?你会怎么做到这一点?
编辑:给每个人指点我的STL容器:我知道它们的存在。但是,我无法在所有情况下使用这些,因为我需要处理的数据量通常很大。这里的想法是实现一个简单的容器,它使用磁盘作为存储而不是内存。
答案 0 :(得分:4)
这不是你应该使用C ++的方式。我强烈建议您研究标准库容器类,例如std :: vector和std :: map,以及模板的使用。继承应始终是最后的设计工具。
答案 1 :(得分:2)
如果你想为你的迭代器使用继承,我建议你使用与STL begin()/end()
不同的方法。
例如,从.NET框架查看IEnumerator
。 (MSDN documentation)
您的基类可能如下所示:
class CollectionBase
{
// ...
virtual IteratorBase* createIterator() const = 0;
};
class IteratorBase
{
public:
virtual bool isEnd() const = 0;
virtual void next() const = 0;
};
// usage:
for (std::auto_ptr<IteratorBase> it = collection.createIterator(); !it->isEnd(); it->next)
{
// do something
}
如果您希望与begin()/end()
保持联系,可以使用dynamic_cast
检查您是否拥有正确的类型:
class MyIteratorBaseImpl
{
public:
virtual bool operator!=(IteratorBase const &other) const
{
MyIteratorBaseImpl * other2 = dynamic_cast<MyIteratorBaseImpl*>(&other);
if (!other2)
return false; // other is not of our type
// now you can compare to other2
}
}
答案 2 :(得分:1)
请执行模仿STL执行容器的方式。这样,就有可能将<algorithm>
与容器一起使用。
答案 3 :(得分:0)
我可以建议你添加迭代器一个虚拟的'entity-id'函数,并在operator!中检查this-&gt; entity_id()和other.entity_id()(my example,'position'函数是这种'entity-id'功能)。