嘿,我有一个关于一般成员函数指针的问题。我正在努力实现类似于以下问题的How to define a general member function pointer
基本上我想要做的是注册一个成员函数指针,该指针接受一个通用的Event对象作为具有特定事件类型的参数(例如,KeyboardEvent)。然后,在我的输入管理类中,我希望能够做的是每当用户点击一个键时,我可以创建一个包含一些关于keypress的数据的KeyboardEvent对象,并调用我注册的所有成员函数指针。 KeyboardEvent类型,我的KeyboardEvent对象作为参数。
我一直在使用boost bind和boost函数,它们似乎使我能够完成我想做的95%,这是我试图将所有成员函数指针存储在向量中的唯一问题,但它们都是不同的类型,所以我不能这样做。所以当我第一次使用我的事件处理系统注册方法时,我将它们绑定到一个函数对象中,它希望我在执行时指定所有参数。此时我没有对象,因为对象是由未来某个未知事件生成的。
很抱歉,如果没有任何意义的话。
答案 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();
}
}