通过函数指针定义类范围之外的方法

Defining methods outside of a class's scope via function pointers

本文关键字:方法 范围 函数 指针 定义      更新时间:2023-10-16

前言

我正在尝试创建一个事件系统。默认情况下,事件不执行任何操作。如果一个对象需要选择加入事件系统,那么只需要程序员为侦听器定义一个可调用的函数。

从理论上讲,这听起来很棒,但实际上我不确定是否可以在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捕获我正在尝试实现的功能。

因此,我尝试了许多建议,并设法创建了一个没有进行太多更改的工作示例。我用 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);
}