我正在为输入处理程序类设计一个方法。这是一些伪代码......
void InputHandler::ScanEvents( boost::function1< void, std::string& > &func ) {
// Scan keys, determining string to pass
// If string found, call func with string as its argument on object tied to func
}
我不确定如何实现它,或者如果它甚至可能,因为函数的重点是将它与调用者分开。这个想法是一个对象有一个私有成员函数和一个持有它的boost :: function成员。每当它在其InputHandler上调用ScanEvents时,它就会传递该函数,因此只要找到适当的事件,ScanEvents就可以“激活它”。
效率是一个问题,因为这是一个性能很重要的领域,而且这个功能经常被调用。
P.S。我发誓我记得在Scott Meyer的一本书中读过这样的例子,但我找不到它的生活。也许它出现在现代C ++设计......看起来......
答案 0 :(得分:3)
boost::function
的开销相当慢 - 约为20ns per call。我不会从内部循环调用它 - 但我也不会调用任何其他类型的函数指针。要调用成员函数,只需使用boost::lambda::bind
构造匿名包装函数:
ih->ScanEvents(boost::lambda::bind(&ThisClass::CallbackFunc, this, boost::lambda::_1));
如果您需要真正高性能的一个选项是使用带有boost::lambda
仿函数参数的inlinable模板函数:
template<typename F>
double democaller(const F &f) {
double x = 1;
for (int i = 0; i < 1000000; i++) {
x = f(x);
}
return x;
}
namespace l = boost::lambda;
void demouser() {
std::cout << democaller(l::_1 + 1);
}
在足够高的优化设置上,lambda表达式可以内联到调用站点,几乎完全消除了开销。
答案 1 :(得分:2)
的内容
class Thingy
{
public:
Thingy() : callback(bind(&Thingy::Callback, this, _1)) {}
void DoStuff()
{
handler.ScanEvents(callback);
}
private:
InputHandler handler;
function<void(string)> callback;
void Callback(string s)
{
cout << "Called with " << s << endl;
}
};
应该做你所描述的。但是回调通过引用获取字符串可能会更有效。
答案 2 :(得分:1)
您可能正在寻找Modern C ++ Design中的命令实现。
boost :: function的开销与执行它所需的开销一样多。它的目的是允许您将“指针”传递给任何可以响应其接口的函数。如果您不需要此行为,则此开销是实际开销。如果你这样做,那么老实说,我看不到比boost :: function更好的方法(它甚至经过优化,以确保在某些实现中不会从虚拟函数中获得大量额外的内存使用)。
可以构造一个导致可能内联代码的方法,但是一旦你尝试将它存储在通用接口中,你就会得到boost :: function开销(可能更多)。
我建议使用boost :: function,直到你发现你真的需要用更快的东西替换它。那么,只有这样你才能编写不同复杂程度的模板来实现它。
简单地存储boost :: function可能足以满足您的需求。您还可以查看boost :: signals。
答案 3 :(得分:0)
通常,在另一个类上调用私有方法并不是最好的主意。
您可以实现一个接口样式的类并继承它,并编写您的ScanEvents方法以期望该类型的输入,例如:
class Notifyable {
public:
virtual void notify(std::string s) = 0;
};
void InputHandler::ScanEvents( Notifyable &n ) {
// Scan keys, determining string to pass
// If string found, call func with string as its argument on object tied to func
n.notify(<string>);
}
我认为这也可能更快,只是因为你使用boost :: function包装器避免了任何可能的开销。