Обратные вызовы c ++ - время компиляции альтернатив виртуальным функциям - PullRequest
3 голосов
/ 15 ноября 2011

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

Универсальный класс:

class LibraryClass
{
private:
    virtual void SomeCallback(){}
};

Код с использованием универсального класса:

class AppClass;

class LibraryClassWrapper: public LibraryClass
{
public:
    LibraryClassWrapper(AppClass& appClass):appClass_(appClass){}
private:
    virtual void SomeCallback();
    AppClass& appClass_;
};

class AppClass
{
public:
    AppClass():libraryClassWrapper_(*this){}
    void handleCallbackFromLibraryClass()
    {
        std::cout << "Handling callback" << std::endl;
    }
private:
    LibraryClassWrapper libraryClassWrapper_;
};

void LibraryClassWrapper::SomeCallback()
{
    appClass_.handleCallbackFromLibraryClass();
}

Это кажетсяужасно много шаблонов, просто чтобы перезвонить.Альтернативой может быть использование функтора, который может быть немного чище.

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

Ответы [ 3 ]

5 голосов
/ 15 ноября 2011

Можно использовать Любопытно повторяющийся шаблон (CRTP) для реализации статического полиморфизма.

3 голосов
/ 15 ноября 2011

Вы можете найти простое использование функции std :: function.Таким образом, клиенты могут реализовать свои классы, однако они считают нужным, а не вынуждены использовать наследование.

Это также предпочтительнее, чем обратный вызов в стиле C, который часто требует указатель void* «пользовательских данных»,способен правильно работать с классами, которые хотят использовать функцию-член.

Вы можете использовать лямбду для захвата любого нужного вам состояния и позволить интерфейсу обратного вызова отражать только то, что имеет отношение к уведомлению.Должно быть так просто, как-то так:

#include <functional>

typedef std::function<void()> CallbackType;

struct Example
{
    void CallbackHandler()
    {
        /* do something */
    }
};

void FreeFunctionHandler()
{
    /* do something */
}

// Use lambda to call member function of 'example'
Example example;
CallbackType callback1 = [&example]() { example.CallbackHandler(); };

// Use free function
CallbackType callback2 = FreeFunctionHandler;

// Execute callbacks
callback1();
callback2();
1 голос
/ 15 ноября 2011

Я думаю, что дизайн на основе политики - это то, что вы ищете:

http://en.wikipedia.org/wiki/Policy-based_design

Основной шаблон был описан в «Современном C ++ Design» Александреску и использовался в сопутствующей библиотеке «Loki». Учитывая это, сама библиотека Loki является отличным справочником о том, как использовать дизайн в соответствии с политикой. Библиотека находится на sourceforge здесь:

http://loki -lib.sourceforge.net / index.php? П = Main.HomePage

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