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

发布于 2024-08-05 10:46:23 字数 258 浏览 2 评论 0原文

考虑这段代码:

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

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

如果答案是视情况而定,那么应该如何做出决定?

Consider the piece of code:

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

Should I expose the whole container, or should I expose typedef'd iterator class and write adaptor methods (begin(), end(), size(), and whatever I need)?

If the answer is it depends, how should one make a decision?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

叹梦 2024-08-12 10:46:23

除非绝对需要公开容器,否则您仅公开迭代器或迭代器范围(以及类型定义的迭代器类型)。

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

You only expose iterators or iterator-ranges (and typedefed iterator types) unless you absolutely need to expose the container.

This avoids breaking other code when changing the implementation details and also follows the guide-lines of information hiding / encapsulation.

丶视觉 2024-08-12 10:46:23

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

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

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++)
  {
  }
}

If you want to follow good design lines,

your map should private or protected, And it should look like

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++)
  {
  }
}
深爱不及久伴 2024-08-12 10:46:23

答案是“视情况而定”。 :)

你的类的用户需要了解多少关于内部向量

以标准库中的stack类为例。它在内部使用标准容器,但它甚至不公开迭代器。它公开了push 和pop 方法,仅此而已。

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

很多时候,类的用户实际上除了迭代器之外不需要任何东西。如果您的 Foo 类公开 begin()end(),我还需要什么?我能够随意访问内部数据结构的每个元素。我可以修改它们中的每一个,或者阅读它们中的每一个。

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

The answer is "it depends". :)

How much does the user of your class need to know about the internal vector?

Take as an example the stack class in the standard library. It uses a standard container internally, but it doesn't even expose iterators. It exposes push and pop methods, and little else.

The user of the class doesn't need to know anything else. The user of the class shouldn't be allowed to access the middle of the stack. If you do that, it is no longer a stack.

Quite often, users of the class don't actually need anything more than iterators. If your Foo class exposes begin() and end(), what else do I need? I'm able to access every element of the internal data structure at will. I can modify each of them, or read each of them.

Do I also need to be able to insert/remove elements? Perhaps, and if so, should I do that directly on the vector, or through your adaptor methods? It depends. What does the object represent? Does it make sense to add objects directly to the vector owned by a Foo? Or does it make sense to add objects to the Foo object, and let it delegate to whatever internal implementation it likes?

秋心╮凉 2024-08-12 10:46:23

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

另一方面,如果 foo 对象只是一个美化的容器,还包含一个向量,那么也许暴露该向量是可以的(注意也许)。请注意,通过公开向量,您将 foo 的用户紧密绑定到 std::vector ,因此在后期将其更改为另一种容器类型可能会更困难。

It depends.
If by changing the state of a pub in the container you are changing the state of the object foo then you should not expose the container (as you may want to limit accesses at a later stage, or make a note of accesses).

If on the other hand foo objects are just a glorified container that also holds a vector then maybe exposing the vector is OK (note the maybe). Note by exposing the vector you are tightly binding the user of foo to a std::vector and thus changing it to another container type at a latter stage may be harder.

花间憩 2024-08-12 10:46:23

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

In case you only need to read from your vector, expose the .begin() .end() and iterator. In case you actually need to add/remove data or change it, expose the entire vector.

z祗昰~ 2024-08-12 10:46:23

不要暴露任何东西,使用精简包装技术包装调用并检查一些明显的问题,例如 null 和索引越界以及类型和健全性检查。

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

Don't expose nothin, wrap the call using thin-wrapper techniques and check for some obvious such as null and index out of bounds as well as type and sanity checks.

See coding horrors here on this site for why, the coder at M$ who found his function call posted on ZD net as patch of the week. If you have to write hand-tweaked zero-time returns and expose it to other sections, you might get hammered by Section 8's

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文