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

时间:2018-10-23 20:02:49

标签: c++ function-pointers

序言

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

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

1 个答案:

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