通用成员函数指针帮助

时间:2010-02-06 02:45:26

标签: c++ generics function-pointers

嘿,我有一个关于一般成员函数指针的问题。我正在努力实现类似于以下问题的How to define a general member function pointer

基本上我想要做的是注册一个成员函数指针,该指针接受一个通用的Event对象作为具有特定事件类型的参数(例如,KeyboardEvent)。然后,在我的输入管理类中,我希望能够做的是每当用户点击一个键时,我可以创建一个包含一些关于keypress的数据的KeyboardEvent对象,并调用我注册的所有成员函数指针。 KeyboardEvent类型,我的KeyboardEvent对象作为参数。

我一直在使用boost bind和boost函数,它们似乎使我能够完成我想做的95%,这是我试图将所有成员函数指针存储在向量中的唯一问题,但它们都是不同的类型,所以我不能这样做。所以当我第一次使用我的事件处理系统注册方法时,我将它们绑定到一个函数对象中,它希望我在执行时指定所有参数。此时我没有对象,因为对象是由未来某个未知事件生成的。

很抱歉,如果没有任何意义的话。

3 个答案:

答案 0 :(得分:3)

(这里有一个更直接的解决你的boost :: function / bind问题,没有所有Boost.Signals2的东西。)

使用boost :: bind时,似乎没有使用_1,_2等占位符。此示例说明了如何使用它们:

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);
}

答案 1 :(得分: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));

答案 2 :(得分:0)

这不是你问题的真正答案,而只是暗示你想要完成的事情已经存在。

您似乎正在尝试实施Observer模式。你可以阅读它here。一旦掌握了Observer模式,请查看Boost.Signals2库。 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();
    }
}