考虑一下这段代码:
class Foo
{ // ...
std::vector<Bar> bars;
};
我应该公开整个容器,还是应该公开typedef
'迭代器类并编写适配器方法(begin()
,end()
,size()
以及我需要的任何内容)?
如果答案是取决于,那么应该如何做出决定?
答案 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节的打击