C 功能指针和成员功能指针

C++ function pointer and member function pointer

本文关键字:功能 指针 成员      更新时间:2023-10-16

是否有一种将功能指针用于函数和成员函数的方法?

我想创建一种可以保留类的成员功能的事件处理程序,同时它应该能够具有"正常"功能指针。

编辑:我找到了一个解决方案。可能不是最好的,而是一个;

event.h

#include <map>
class BasicEvent {
public:
    BasicEvent(int id) : eventId(id)
    {}
    int GetId() const
    { 
        return eventId;
    }
    virtual void ObjectMethode() {}
protected:
    const int eventId;
};
class BasicEventHandler {
public:
    void Trigger(BasicEvent* event)
    {
        if (this->eventMap.find(event->GetId()) != this->eventMap.end()) {
            eventMap[event->GetId()](event);
        }
    }
    void AddEvent(int id, std::function<int(BasicEvent*)> eventFunction)
    {
        eventMap[id] = eventFunction;
    }
    void RemoveEvent(int id)
    {
        this->eventMap.erase(id);
    }
private:
    std::map<int, std::function<int(BasicEvent*)>> eventMap;
};

main.cpp

class CustomEvent : public BasicEvent {
public:
    CustomEvent(int id) : tq::BasicEvent(id)
    {
    x = 9;
    y = 8;
    }
    struct {
    int x;
    int y;
};
    void ObjectMethode()
    {
    std::cout << this->eventId << " Custom Event: X: " << x << " Y: " << y << 'n';
    }
};

int main() {
    BasicEventHandler myHandler;
    myHandler.AddEvent(0, [&](BasicEvent* event) {
        std::cout << " EVENT <" << event->GetId() << "> Triggered!n";
    return 0;
    });
    myHandler.AddEvent(1, [&](tq::BasicEvent* event) {
    event->ObjectMethode();
    return 0;
    });
    myHandler.Trigger(&BasicEvent(0));
    myHandler.Trigger(&CustomEvent(1));
    return 0;
}

c 11和lambdas ..是的!!

所以我们去..

让我们拥有一个函数,您的事件处理程序将采用 predicate (返回true或false的函数(和两个函数,即on_sucesson_error

如果test_predicate返回true,则应调用on_success,否则on_error将被调用。

template<typename Predicate, typename OnSucess, typename OnError>
void single_event_handler (Predicate && test_predicate,
                           OnSucess  && on_success,
                           OnError   && on_error)
{
    if( test_predicate() )
        on_success();
    else
        on_error();
}

现在我们的来电者一侧。在这里,我们有3个要适合此模式的功能。

bool is_even(int num) { return !(num % 2); }
void on_even_found() { std::cout << "Number passed is evenn"; }
void on_odd_found() { std::cout << "Number passed is oddn"; };

,但是如您所见,is_even功能不适合test_predicate的签名。 is_even(int)采用一个参数,而 test_predicate()不采用任何参数。

那么我们如何解决此问题?

我们将其包装到另一个功能和/或lambda中,然后将其传递。

指导原理:可以通过再增加一层来解决每个问题。

// wrap it in another function or lambda
auto is_5_even = []() { return is_even(5); };
auto is_4_even = []() { return is_even(4); };

现在,一旦我们的所有难题准备就绪,我们就会创建自己的活动处理程序。

// caller side - pair the final structure
single_event_handler(is_5_even, on_even_found, on_odd_found);
single_event_handler(is_4_even, on_even_found, on_odd_found);

现在,可以通过使用绑定和功能指针在C 11中实现此代码。可悲的是,std::bindstd::function在C 11中引入了,您必须使用其他替代方案,例如Boost Library。

此外,可以将另一个包装器写在single_event_handler的顶部,可以立即管理多个事件,但是我认为我们必须创建另一个函数register_event,以便可以有效地使用它。

这是完整的工作代码,供您参考(使用g++ -std=c++11编译(

#include <iostream>
template<typename Predicate, typename OnSucess, typename OnError>
void single_event_handler (Predicate && test_predicate,
                           OnSucess  && on_success,
                           OnError   && on_error)
{
    if( test_predicate() )
        on_success();
    else
        on_error();
}
bool is_even(int num) { return !(num % 2); }
void on_even_found() { std::cout << "Number passed is evenn"; }
void on_odd_found() { std::cout << "Number passed is oddn"; };
int main()
{
    // caller side
    auto is_5_even = []() { return is_even(5); };
    auto is_4_even = []() { return is_even(4); };
    single_event_handler(is_5_even, on_even_found, on_odd_found);
    single_event_handler(is_4_even, on_even_found, on_odd_found);
    return 0;
}

成员函数将在哪里获得"此"指针?这两个功能不能具有相同的签名。可能,您最好的选择是创建一个lambda,它将捕获"此",然后将其发送给您的活动操作员。

std::function将能够为您持有。

接受您的处理程序作为std::function,然后客户可以通过他们想要的任何东西传递。无论是功能,lambdas,其他函子,您都会命名。

模板将为您处理详细信息,客户可以选择他们希望被称为的方式。