我应该在 C++ 中公开迭代器和适配器方法还是整个容器?
考虑这段代码:
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
除非绝对需要公开容器,否则您仅公开迭代器或迭代器范围(以及类型定义的迭代器类型)。
这可以避免在更改实现细节时破坏其他代码,并且还遵循信息隐藏/封装的准则。
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.
如果你想遵循良好的设计路线,
你的地图应该是私有的或受保护的,它应该看起来像
If you want to follow good design lines,
your map should private or protected, And it should look like
答案是“视情况而定”。 :)
你的类的用户需要了解多少关于内部
向量
?以标准库中的
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 exposesbegin()
andend()
, 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 theFoo
object, and let it delegate to whatever internal implementation it likes?这取决于。
如果通过更改容器中 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.
如果您只需要从向量中读取,请公开 .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.
不要暴露任何东西,使用精简包装技术包装调用并检查一些明显的问题,例如 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