C ++ 11替代Java匿名回调类 [英] C++11 alternative to the Java anonymous callback class
问题描述
我意识到,我在这里的解决方案是远非理想与C + +,所以我问什么是一个合适的C ++程序员在这种情况下会做。 (C ++ 11)
I realise that the solution I have here is far from ideal with C++, so I'm asking what a proper C++ programmer would do in this situation. (C++11)
我有一个 DialogBox
类,它存储一组按钮。目前我有一个纯抽象内部类 DialogBox :: Button
与纯虚函数 virtual void callback()const
。
I have a DialogBox
class, which stores a collection of buttons. At the moment I have a pure abstract inner class DialogBox::Button
with the pure virtual function virtual void callback() const
.
从Java我习惯于使用这个策略创建和实例化一个匿名类派生自Button in-place实现回调函数。类似这样的东西:
From Java I'm used to using this strategy to create and instantiate an anonymous class deriving from Button in-place which implements the callback function. Something like this:
db.add_button(new Button( "Button text", BUTTONTYPE ) {
public void callback() {
// Callback code
}});
这是C ++解决方案的提示。
which is what prompted this C++ solution.
我的C ++解决方案因此看起来像
My C++ solution therefore looks like
dialogbox.h
class DialogBox {
public:
// Abstract class for buttons with callback functions
class Button;
private:
/* ...
stuff
*/
public:
/* ...
stuff
*/
const std::vector< unique_ptr<DialogBox::Button> >& get_buttons() const;
void add_button( unique_ptr<DialogBox::Button>& new_button );
};
class DialogBox::Button {
private:
/* ...
stuff
*/
public:
// Constructor
Button( const string& button_text, const DialogButtonType button_type = DialogButtonType::NORMAL );
/* ...
stuff
*/
// Virtual callback function
virtual void callback() const = 0;
};
用法:
// Instantiate
DialogBox db{ /* ... args ... */ };
// Test adding buttons
class Button1 : public DialogBox::Button {
using DialogBox::Button::Button;
public: void callback() const {
// Callback code
}
};
std::unique_ptr<DialogBox::Button> button1{ new Button1{ "Button1", DialogButtonType::ENTER } };
db.add_button( button1 );
这可以工作,但它显然不像Java版本那么干净,当然感觉像是我的鞋在C ++不是要做的事情。
This works, but it's clearly not as clean as the Java version and certainly feels like I'm shoehorning in something that C++ is not designed to do.
那么,C ++程序员怎么做呢?看来概念上将Button作为一个类是正确的(因为它有内部数据和它自己的行为)。目前我正在考虑使用lambda表达式将回调函数传递给Button的构造函数,但我想我会得到一些关于这个问题的专家意见。
So, how would a C++ programmer do this? It seems conceptually right to have Button as a class (since it has internal data and its own behaviour). At the moment I'm thinking of using a lambda expression to pass in the callback function to Button's constructor, but I thought I'd get some expert opinion on the subject.
推荐答案
C ++ 11解决方案是让 Button
看起来像这样。为了简洁,我跳过 string
和 DialogButtonType
参数:
The C++11 solution would be to have Button
look something like this. I'm skipping the string
and DialogButtonType
parameters for brevity:
class Button {
public:
template <typename F>
Button(F&& f) : cb(std::forward<F>(f))
{ }
void callback() { cb(); }
private:
std::function<void()> cb; // type-erased functor for ANY callable
// that takes zero arguments
};
这允许你有一个容器 Button
在回调中完全任意的事情
s - 不需要继承。它还允许你通过提供一个任意的回调函数作为构建过程的一部分,在飞行中伟大的一次性按钮:
This allows you to have a container of Button
s that do completely arbitrary things in their callback
s - no inheritance necessary. It also allows you to great one-off buttons on the fly by providing them with an arbitrary callback functor as part of the construction process:
db.add_button(std::make_unique<Button>([=]{
// arbitrary Callback code
}));
注意, add_button
绝对以值 unique_ptr
为参数,而不是引用。
As a side-note, add_button
should definitely take its unique_ptr
argument by value, not by reference.
这篇关于C ++ 11替代Java匿名回调类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!