【问题标题】:Public boost::signal object公共提升::信号对象
【发布时间】:2010-10-07 15:29:18
【问题描述】:
我公开我的boost::signals 因为我很懒。
class Button {
public:
signal<void()> clicked;
};
int main() {
Button btn;
btn.clicked.connect(handleClick);
}
... 而不是用Button::OnClicked(boost::function<void()>) 封装。
这会回来咬我吗?
【问题讨论】:
标签:
c++
boost-signals
public-fields
【解决方案1】:
这取决于。
每次一个对象连接到另一个对象的信号时,我都想添加一些特殊的逻辑,这让我很苦恼。这是最有可能咬你的情况。
此外,当其他对象连接到任何给定对象时,很难准确跟踪。
为了安全起见,我会说将连接隐藏在函数后面。
我通常使用宏来定义 vanilla 函数。
#define SIGNAL(slot,name) connection name(function<slot> func) { return _##name##.connect(func);}
然后在类定义中:
SIGNAL(void(),clicked)
这假设您遵循命名信号“_clicked”的约定,但您可以替换任何约定。它通常使所有类的界面更干净。当您想添加特殊的连接逻辑时,您可以在不更改使用该信号的所有其他对象的情况下。
编辑
一个实例是信号对象实际移动到另一个类中的委托实现时,但对象通过原始类连接仍然有意义。这破坏了所有试图连接到它的地方。如果他们一直在使用函数访问器进行连接,那么就像更改函数以在委托中查找信号一样简单。但是因为它破坏了原始类的所有用户。
或者,当我想记录每次连接到特定信号的东西时。这仅用于调试目的,但如果您怀疑信号连接中的循环等异常情况正在发生,它会非常有用。
【解决方案2】:
我偶然发现了一个很好的理由不这样做。
我们正在考虑使用在外部接口上公开 boost::signals 的第三方库。这个库依赖于带有一组编译器定义的 boost 版本,这些编译器定义与我们在项目中使用的标准 Visual Studio 编译器定义二进制不兼容。每当我们尝试调用第三方库的 signal.connect 时,事情就会死掉。
我们的解决方案是:
- 使用它们提供的 boost 版本重新编译我们所有的源库和依赖库。
- 封装升压信号并隐藏实现
至少要考虑一些事情!
【解决方案3】:
嗯,这个问题真的与boost::signal 或function 无关——都是关于封装的。
Button 类的客户是否需要完全访问clicked?如果他们应该能够做的就是订阅它,那么只允许使用 OnClicked 方法。暴露更多可能会咬你恕我直言。
一如既往地平衡成本与收益。在这种情况下,成本非常低。如果您在我的团队中,我强烈建议您添加 OnClicked 方法。
【解决方案4】:
我也将它们设为公开,并使用大写字母作为其对象名称。这种方法从来没有适得其反。