代码之家  ›  专栏  ›  技术社区  ›  TC.

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

  •  0
  • TC.  · 技术社区  · 16 年前

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

    集合H

    class Collection
    {
        CollectionBase *d_base;
    public:
        Collection(CollectionBase *base);
    
        Iterator begin() const;
    };
    
    inline Iterator Collection::begin() const
    {
        return d_base->begin();
    }
    

    收藏库.h

    class CollectionBase
    {
    public:
        virtual Iterator begin() const = 0;
        virtual Iterator end() const = 0;
    };
    

    迭代器

    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);
    }
    

    迭代器数据库.h

    class IteratorBase
    {
    public:
        virtual bool operator!=(IteratorBase const &other) const = 0;
    };
    

    使用此设计,集合的不同实现派生自 CollectionBase 并且可以通过返回 Iterator 它包含了 IteratorBase .

    到目前为止一切都很好。我目前正在尝试解决如何实现 operator!= 不过。 迭代器 将呼叫转接到 迭代基 ,但是应该如何在那里实现该运算符?一个简单的方法就是 迭代基 在的实现中引用适当的类型 迭代基 然后进行具体的比较,以实现 迭代基 . 这假设您将表现得很好,但不会传递两种不同类型的迭代器。

    另一种方法是执行某种类型的类型检查,检查迭代器是否属于同一类型。我相信这个检查必须在运行时进行,考虑到这是一个迭代器,我宁愿不执行昂贵的运行时类型检查。 接线员!= .

    我这里是否缺少更好的解决方案?也许有更好的替代类设计(当前的设计是从我在C++课程中学到的东西来适应的)?你会怎么处理这个问题?

    编辑: 所有人都指向我的STL容器:我知道它们的存在。但是,我不能在所有情况下都使用它们,因为我需要处理的数据量通常都很大。这里的想法是实现一个简单的容器,它使用磁盘作为存储,而不是内存。

    4 回复  |  直到 16 年前
        1
  •  2
  •   Miroslav BajtoÅ¡    16 年前

    如果您想为迭代器使用继承,我建议您使用与STL不同的方法 begin()/end() .

    看一看 IEnumerator 例如,来自.NET框架。( 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
        }   
    

    如果你想留下来 开始()/结束() ,你可以使用 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
  •  4
  •   anon    16 年前

    这不是你应该使用C++的方式。我强烈建议您研究标准库容器类,如std::vector和std::map,以及模板的使用。继承应该永远是最后的设计工具。

        3
  •  1
  •   DevSolar    16 年前

    拜托 模仿STL做容器的方式。这样,就可以使用 <algorithm> 用你的容器。

        4
  •  0
  •   Sergey Miryanov    16 年前

    我可以建议您在迭代器中添加一个虚拟的“entiy id”函数,并在运算符中添加!=检查此->实体_id()和其他。实体_id()。( my example ,“position”函数就是这样的“entity id”函数)。