Поддерживает ли C ++ 0x анонимные внутренние классы? - PullRequest
3 голосов
/ 23 декабря 2011

Скажем, у меня есть слушатели, встроенные в C ++ 98, они абстрактные и должны, например, реализовывать ActionPerformed.В C ++ 0x есть способ сделать похожий на Java:

button.addActionListener(new ActionListener() {
public void actionPerfored(ActionEvent e)
{
// do something.
}
});

Спасибо

Ответы [ 4 ]

6 голосов
/ 23 декабря 2011

Не совсем, но вы можете сделать что-то близкое с Lambdas.

т.е:.

class ActionListener
{
public:
   typedef std::function<void(ActionEvent&)> ActionCallback;

public:
   ActionListener( ActionCallback cb )
      :_callback(cb)
   {}

   void fire(ActionEvent& e )
   {
      _callback(e);
   }

private:
   ActionCallback _callback;
};


..
button.addActionListener( new ActionListener(
   []( ActionEvent& e )
   {
       ...
   }
));
5 голосов
/ 23 декабря 2011

Это C ++, а не Java, поэтому написание C ++, подобного Java, не будет работать хорошо.

В любом случае, вы можете создать функцию адаптера.Предположим, что

typedef int ActionEvent; // <-- just for testing

class ActionListener
{
public:
    virtual void actionPerformed(const ActionEvent& event) = 0;
};

Тогда мы могли бы написать шаблонный подкласс ActionListener, который оборачивает объект функции:

#include <memory>

template <typename F>
class ActionListenerFunctor final : public ActionListener
{
public:
    template <typename T>
    ActionListenerFunctor(T&& function)
        : _function(std::forward<T>(function)) {}

    virtual void actionPerformed(const ActionEvent& event)
    {
        _function(event);
    }
private:
    F _function;
};

template <typename F>
std::unique_ptr<ActionListenerFunctor<F>> make_action_listener(F&& function)
{
    auto ptr = new ActionListenerFunctor<F>(std::forward<F>(function));
    return std::unique_ptr<ActionListenerFunctor<F>>(ptr);
}

, а затем использовать make_action_listener для переноса лямбда-выражения, например (http://ideone.com/SQaLz).

#include <iostream>

void addActionListener(std::shared_ptr<ActionListener> listener)
{
    ActionEvent e = 12;
    listener->actionPerformed(e);
}

int main()
{
    addActionListener(make_action_listener([](const ActionEvent& event)
    {
        std::cout << event << std::endl;
    }));
}

Обратите внимание, что это далеко от идиоматического C ++, где в addActionListener() вам просто нужно взять const std::function<void(const ActionEvent&)>& или даже параметр шаблона для максимальной эффективности и указать лямбдунепосредственно.

5 голосов
/ 23 декабря 2011

Нет, вы не можете этого сделать.

Если вы отказываетесь от "похожего на Java" и просто используете функтор, вы найдете лямбды C ++ 11 очень полезными.

1 голос
/ 23 января 2012

Я думаю, что мы можем сделать это в C ++, используя лямбды

button.addActionListener([]()->ActionListener*{ struct A: ActionListener {
void actionPerfored(ActionEvent e)
{
// do something.
}
}; return new A;}());

Должно быть легко обернуть это в макрос.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...