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