序言
我正在尝试创建一个事件系统。默认情况下,事件不会执行任何操作。如果一个对象需要选择加入事件系统,那么程序员只需要为侦听器定义一个可调用函数即可。
从理论上讲,这听起来不错,但实际上我不确定是否可以在C ++中实现这种事情。这是我想像的代码示例。
概述
#include <iostream>
enum Color{ red, green, blue };
class Event {
public:
// Would be called within the context of a loop.
// Each time we go through the loop, we would have different input.
void listen(const Color& color) {
// If the callable is defined, then call it.
if(callable) callable(color);
}
// We would pass in function to be called within listen()
void defineAction(void(*function)(const Color &color)) {
callable = function;
}
private:
void (*callable)(const Color& color) = nullptr;
};
class Greeter: public Event {
void greet() { std::cout << "Hello" << std::endl; }
};
int main(int argc, char** argv) {
Greeter greeter;
// This doesn't work for two reasons. We cannot define a function here,
// and scoping rules wont allow for an implicit this->greet().
// Ideally, I would like to do this inline with a lambda
/*void greetIfRed(const Color& color) {
if(color == red)
// call greet().
}
greeter.defineAction(&greetIfRed);
*/
}
扩展这个想法
基本上,每次我们经过事件循环时,Event类都会收到会发生变化的东西。在此示例中,我选择了颜色,但是颜色可以是鼠标坐标,整数或其他形式。该类型需要事先进行严格定义。
在我的设计中,我不希望事件循环中具有哪些类。我们可以有一个迎宾员,一个参与者,或者只是告别的东西。我认为事件循环看起来像这样。 (伪代码)
while(event) {
greeter.listen(event)
player.listen(event)
text.listen(event) // e.g.,the text could change color if the mouse is over it,
}
问题
是否可以通过利用所述类方法的函数指针来定义类范围之外的方法?这将需要为子类工作。类Greet
和函数greetIfRed
捕获了我试图实现的功能。
答案 0 :(得分:0)
因此,我尝试了许多建议,并且设法创建了一个有效的示例,而没有进行太多更改。我用C ++ 14编译的。
#include <iostream>
#include <functional>
enum Color{ red, green, blue };
class Event {
public:
void listen(const Color& color) {
if(callable) callable(color);
}
void defineAction( std::function<void(const Color& color)> function) {
callable = function;
}
protected:
std::function<void(const Color& color)> callable = nullptr;
};
class Greeter: public Event {
public:
void greet() { std::cout << "Hello" << std::endl; }
};
int main()
{
Greeter greeter;
greeter.defineAction([&greeter](const Color& color){
if(color == red)
greeter.greet();
});
greeter.listen(red);
greeter.listen(green);
}