Хороший способ реализовать применимые Обратные вызовы в C++

Ну, причиной использовать указатель было бы точно то же, которое причина использовать указатели в C выделила с malloc: если Вы хотите свой объект жить дольше, чем Ваша переменная!

Это даже настоятельно рекомендовано для НЕ использования нового оператора, если можно избежать его. Особенно, если Вы используете исключения. В целом намного более безопасно позволить компилятору освободить Ваши объекты.

6
задан Jon Seigel 4 April 2010 в 16:09
поделиться

7 ответов

Ваш подход требует, чтобы функции обратного вызова были либо свободными, либо статическими членами класса. Это не позволяет клиентам использовать функции-члены в качестве обратных вызовов. Одно из решений - использовать boost :: function в качестве типа обратного вызова:

typedef boost::function<void (MenuItem*)> callback_type;
AddItem(const std::string& s, const callback_type& callback = callback_type());

Клиенты могут затем использовать boost :: bind или boost :: lambda для передачи обратного вызова:

menu->AddItem("Open", boost::bind(&MyClass::Open, this));

Другой вариант - использовать boost :: signal , который позволяет нескольким обратным вызовам регистрироваться для одного и того же события.

10
ответ дан 8 December 2019 в 04:54
поделиться

Мне нравится ваш подход. Одной из альтернатив может быть объявление интерфейса, который в некотором смысле является «объектно-ориентированным эквивалентом» обратного вызова:

class IMenuEntry {
public:
    virtual void OnMenuEntrySelected(MenuItem* item) = 0;
};

Регистрационная подпись станет

AddItem(string s, IMenuEntry * entry);

И реализация метода

class MyApp : public IMenuEntry {
public:
    virtual void OnMenuEntrySelected(MenuItem* item){
        activeMode = item->text;
    }
}

Интерфейсный подход позволит вам избежать «void * обходной путь» для отсутствующего указателя this .

8
ответ дан 8 December 2019 в 04:54
поделиться

Вы можете взглянуть на использование boost :: bind .

menu->AddItem(TRANSLATE, 
              "translate", 
              boost::bind( &MyApp::OnModeSelected, this, _1, _2 ));
3
ответ дан 8 December 2019 в 04:54
поделиться

Я настоятельно рекомендую посмотреть ] boost :: function и boost: bind для этого. Его изучение упростит привязку ваших функций в сто раз.

1
ответ дан 8 December 2019 в 04:54
поделиться

Я не вижу ничего плохого, кроме того, что сигнатуру указателя функции трудно прочитать. Но я бы, вероятно, наблюдатель паттерн, чтобы добиться этого.

1
ответ дан 8 December 2019 в 04:54
поделиться

Прочтите этот технический документ. Он строит различные методы для механизма обратного вызова, достаточно подробно анализируя производительность, удобство использования и другие компромиссы. Я нашел это трудным для чтения: - (

1
ответ дан 8 December 2019 в 04:54
поделиться

Вы можете использовать функтор для инкапсуляции вашего обратного вызова. Это позволит вам использовать функцию в стиле C или объектный интерфейс для обеспечения обратного вызова.

0
ответ дан 8 December 2019 в 04:54
поделиться
Другие вопросы по тегам:

Похожие вопросы: