提供迭代器的集合的C ++类层次结构

时间:2009-12-11 11:19:00

标签: c++ wrapper iterator

我目前正在开展一个项目,我想在其中定义一个可以以不同方式实现的通用“集合”界面。集合接口应指定集合具有按值返回迭代器的方法。使用包装指针的类我得到了以下(大大简化):

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容器:我知道它们的存在。但是,我无法在所有情况下使用这些,因为我需要处理的数据量通常很大。这里的想法是实现一个简单的容器,它使用磁盘作为存储而不是内存。

4 个答案:

答案 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'功能)。