组件A拥有一个包含指针的集合,我计划设计一个API来返回集合。 目前其他组件只读取集合的内容,无意改变任何内容,我将从API返回。
选项包括:
1.返回该集的副本
2.返回集合的引用
3.返回一对set的迭代器。 write_log(fp, event, i/*int*/);
write_log(fp, event, f/*float*/);
关注的是: 1.复制可能需要一些开销。 2.这暴露了内部集,它无法阻止其他组件改变它。 3.如果组件A修改了集合,它是否会使迭代器无效?
答案 0 :(得分:0)
暂时让我们假设您对此有所了解:ComponentA
拥有
一组指针,std::set<Thing *>
,你希望它有一个方法来返回该集,但是
这样接收客户端代码就无法修改它。您不确定是否:
begin()
,end()
)范围。不要做其中任何一件事。每个人都有你自己认定的缺陷, 并且 3 还有一个额外的缺陷,即它不会返回集合。客户端 接收迭代器范围的代码不知道它划分集和 无法利用集的定义属性。
而是从const
方法返回对该集合的const
引用:
struct ComponentA
{
...
...
std:set<Thing *> const & get_set_of_things() const {
return things;
}
private:
std::set<Thing *> things
...
};
这消除了 2 的缺点 - 客户端代码无法修改设置
一个const
参考 - 它没有任何其他障碍。
我希望能回答你的问题,但我担心这不是你设计问题的终结。
客户端代码无法通过修改things
std:set<Thing *> const &
返回get_set_of_things()
。但
我无法修改的东西是那套的成员,仅仅是
指针到Thing
。我当然不在乎那些指针是什么 - 内存地址就像
0x1a04c20
- 我没有兴趣修改他们。但没什么
阻止我修改那些指针的任何Things
指向,例如
ComponentA ca;
...
auto const & things = ca.get_set_of_things;
Thing * pthing = *things.begin();
thing->modify();
...
这会修改由Things
控制的ca
之一 - 这就是你
想防止。
但是,您从ComponentA
对象返回该集合,则无法阻止客户端进行修改
只要你给它们Things
指针,对象就会控制Thing *
。
您可以通过将things
更改为一组const
来阻止此威胁
指针:
struct ComponentA
{
...
...
std:set<Thing const *> const & get_set_of_things() const {
return things;
}
private:
std::set<Thing const *> things
...
};
但是,这种变化的后果是现在ComponentA
本身不能
修改由Things
控制的任何things
。你能忍受吗?
这只是触发的几个响亮设计警报中的第一个
通过您的ComponentA
控制指针集的信息。
我建议你起草你的课程定义并将其付诸实践
对SO的姊妹网站Code Review发表评论。
探索所有可能存在的陷阱,尤其是超出了SO的范围
在没有任何代码的情况下。