2010-02-06 5 views
0

Эй, у меня есть вопрос об указателях функций общего члена. Я пытаюсь добиться чего-то похожего на следующий вопрос: How to define a general member function pointerПомощник указателя функции общего элемента

По существу, я хочу, чтобы иметь возможность зарегистрировать указатель на функцию-член, который принимает общий объект Event в качестве аргумента с определенным типом события (например , KeyboardEvent). Затем, в моем классе управления вводами, я хочу, чтобы каждый раз, когда пользователь нажимает на ключ, я могу создать объект KeyboardEvent, который содержит некоторые данные о нажатиях клавиш, и вызвать все те указатели функций-членов, которые я зарегистрировал с помощью тип KeyboardEvent с моим объектом KeyboardEvent в качестве параметра.

Я играю с функцией boost bind и boost, и они, похоже, позволяют мне делать 95% того, что я хочу сделать, единственная проблема, которую я пытаюсь сохранить все указатели функций-членов в векторе , но все они разные, поэтому я не могу этого сделать. Поэтому я привязываю их к объекту функции, когда я впервые регистрирую метод с помощью моей системы обработки событий, которая ожидает, что я укажу все аргументы на этом этапе выполнения. На данный момент у меня нет объектов, но поскольку объекты генерируются каким-то неизвестным событием в будущем.

Извините, если это не имеет никакого смысла.

+0

Непонятно, в чем вопрос ... вы просто прогуливаетесь на несколько абзацев. Что именно вы хотите знать? Как хранить различные типы объектов в векторе? Или что-то другое? Фрагменты кода всегда помогают. – SoapBox

ответ

3

(Вот более прямой ответ на повышение :: задачи функция/привязки, без всего материала Boost.Signals2.)

Кажется, вы не используете _1, _2 и т.д. заполнители при использовании boost :: bind. Этот пример иллюстрирует, как вы должны их использовать:

struct KeyboardEvent { char key; }; 

typedef boost::function<void (KeyboardEvent)> KeyboardHandler; 

struct Handler 
{ 
    void onKey(KeyboardEvent event) {std::cout << event.key;} 
}; 

int main() 
{ 
    Handler handler1, handler2; 
    std::vector<KeyboardHandler> handlers; 
    handlers.push_back(boost::bind(&Handler::onKey, &handler1, _1)); 
    handlers.push_back(boost::bind(&Handler::onKey, &handler2, _1)); 
    KeyboardEvent event; 
    event.key = 'z'; 
    handlers[0](event); 
    handlers[1](event); 
} 
+0

Вау, это и было. Я пробовал это раньше, но он не компилировался. Я, должно быть, делал что-то еще неправильно. Большое спасибо за помощь. И спасибо за ссылку на шаблон наблюдателя. Я должен буду это прочитать. Я не понимал, что он уже существует на C++. Я просто моделировал дизайн после событий ActionScript 3. – Morgan

0

, если я правильно понимаю ваш вопрос, вы можете попробовать следующее

// function pointer, function with similar signature can be cast as function_t 
typedef int (*function_t)(object_t *event, ...); 
std:: vector<function_t> function_pointers; 

// populate vector, e.g. function_pointers.push_back((function_t)&some_function) 

void handle_event(object_t *event) { 
    for (...) (function_pointers.at(i))(event, ...); 
} 

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

struct base { 
    virtual void function(event_t *event)= 0; 
}; 

template<class A> 
struct F : base { 
    F(A &a) : object_(a) {} 
    virtual void function(event_t *a) { object_.function(a); } 
    A &object_; 
}; 

std:: vector<base*> callback_vector; 
... 
callback_vector.push_back(new F<event_handler>(event_handler_object)); 
0

Это не ответ на вашу проблему, а лишь намек на то, что то, что вы пытаетесь достичь, уже существует.

Похоже, вы пытаетесь реализовать шаблон Observer. Вы можете прочитать об этом here. После того как вы схватили шаблон Observer, просмотрите библиотеку Boost.Signals2. A boost::signal - это вектор указателей функций обработчика событий, но гораздо более мощный.

Вот пример использования Boost :: Signals2 для обнаружения введенных символов. Надеюсь, поможет.

#include <iostream> 
#include <boost/signals2.hpp> 
#include <boost/bind.hpp> 

//----------------------------------------------------------------------------- 
struct KeyboardEvent 
{ 
    char key; 
}; 

//----------------------------------------------------------------------------- 
class Keyboard 
{ 
private: 
    typedef boost::signals2::signal<void (KeyboardEvent)> SignalType; 
    SignalType signal_; 

public: 
    typedef SignalType::slot_type SlotType; 

    // Subscribes to keyboard events 
    boost::signals2::connection connect(const SlotType& slot) 
    { 
     return signal_.connect(slot); 
    } 

    // Scans for keyboard events and notifies subscribers 
    void scan() 
    { 
     KeyboardEvent event; 
     std::cin >> event.key; 
     signal_(event); 
    } 
}; 

//----------------------------------------------------------------------------- 
class KeyPrinter 
{ 
private: 
    void onKey(KeyboardEvent event) 
    { 
     std::cout << "You hit \'" << event.key << "\'\n"; 
    } 

    boost::signals2::connection connection_; 

public: 
    void connect(Keyboard& keyb) 
    { 
     connection_ = keyb.connect(
      boost::bind(&KeyPrinter::onKey, this, _1)); 
    } 
    void disconnect() {connection_.disconnect();} 
}; 

//----------------------------------------------------------------------------- 
class Quitter 
{ 
private: 
    void onKey(KeyboardEvent event) 
    { 
     if (event.key == 'q' || event.key == 'Q') {quit_ = true;} 
    } 

    boost::signals2::connection connection_; 
    bool quit_; 

public: 
    void connect(Keyboard& keyb) 
    { 
     quit_ = false; 
     connection_ = keyb.connect(
      boost::bind(&Quitter::onKey, this, _1)); 
    } 
    void disconnect() {connection_.disconnect();} 
    bool quitDetected() {return quit_;} 
}; 

//----------------------------------------------------------------------------- 
int main() 
{ 
    Keyboard keyb; 
    KeyPrinter printer; 
    Quitter quitter; 

    printer.connect(keyb); 
    quitter.connect(keyb); 

    while (!quitter.quitDetected()) 
    { 
     keyb.scan(); 
    } 
} 
Смежные вопросы