C ++ 11替代Java匿名回调类 [英] C++11 alternative to the Java anonymous callback class

查看:198
本文介绍了C ++ 11替代Java匿名回调类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我意识到,我在这里的解决方案是远非理想与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 DialogBu​​ttonType 参数:

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 Buttons that do completely arbitrary things in their callbacks - 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆