我应该在C ++中公开迭代器和适配器方法或整个容器吗?

时间:2009-09-27 17:45:59

标签: c++ stl interface containers

考虑一下这段代码:

class Foo
{ // ...
    std::vector<Bar> bars;
};

我应该公开整个容器,还是应该公开typedef'迭代器类并编写适配器方法(begin()end()size()以及我需要的任何内容)?

如果答案是取决于,那么应该如何做出决定?

6 个答案:

答案 0 :(得分:8)

除非绝对需要公开容器,否则只暴露迭代器或迭代器范围(以及typedefed迭代器类型)。

这可以避免在更改实现细节时破坏其他代码,并遵循信息隐藏/封装的指导原则。

答案 1 :(得分:4)

如果你想遵循良好的设计线,

你的地图应该是私有的还是受保护的,它看起来应该是

class Foo
{  
    public:
    typedef std::vector<Bar>::const_iterator FooIterator;
    FooIterator begin()
    {
      return bars.begin();
    }
    FooIterator end()
   {
    return bars.end();
   }
    protected:
    std::vector<Bar> bars;

};

int main()
{
   Foo obj;
   for(obj::FooIterator itr=obj.begin();itr!=obj.end();itr++)
  {
  }
}

答案 2 :(得分:2)

答案 “取决于”。 :)

您的班级用户需要了解内部vector

以标准库中的stack类为例。它在内部使用标准容器,但它不会甚至暴露迭代器。它暴露了推送和弹出方法,而没有其他方法。

班级的用户不需要知道任何其他内容。不应允许该类的用户访问堆栈的中间位置。如果你这样做,它就不再是一个堆栈了。

通常,类的用户实际上不需要比迭代器更多的东西。如果您的Foo课程公开begin()end(),我还需要什么?我可以随意访问内部数据结构的每个元素。我可以修改它们中的每一个,或者阅读它们中的每一个。

我还需要能够插入/删除元素吗?也许,如果是这样,我应该直接在向量上,还是通过适配器方法?这取决于。该对象代表什么?将对象直接添加到Foo拥有的向量是否有意义?或者将对象添加到Foo对象并让它委托给它喜欢的任何内部实现是否有意义?

答案 3 :(得分:1)

取决于 如果通过更改容器中 pub 的状态,您正在更改对象的状态 foo ,那么您不应该公开容器(因为您可能希望限制访问稍后阶段,或记录访问权。)

另一方面,如果 foo 对象只是一个美化的容器,它也拥有一个矢量,那么可能会暴露矢量就可以了(注意也许)。请注意,通过公开向量将 foo 的用户紧密绑定到std :: vector,因此在后一阶段将其更改为另一个容器类型可能会更难。

答案 4 :(得分:0)

如果您只需要从向量中读取,请公开.begin()。end()和迭代器。如果您确实需要添加/删除数据或更改数据,请展开整个矢量。

答案 5 :(得分:0)

不要暴露nothin,使用thin-wrapper技术包装调用并检查一些明显的例如null和index out of bounds以及类型和健全性检查。

在这个网站上看到编码恐怖的原因,M $的编码员在ZD网上发布了他的函数调用作为本周的补丁。如果你必须编写手工调整的零时间返回并将其暴露给其他部分,你可能会受到第8节的打击