缺少对成员函数的绑定指针的调用

时间:2016-02-06 10:02:01

标签: c++ function templates pointers c++11

我正在尝试使用模板实现通用事件处理系统,但是当我尝试将该函数添加到列表时,我在编译时遇到错误。

  

错误C2298:缺少对成员函数的绑定指针的调用

class EventManager
{
public:
    template <class OBJECT>
    void subscribe(std::string eventName, OBJECT *obj, void(OBJECT::*newEvent)(Event))
    {
        (obj->*newEvent)(Event()); // I can call the event just fine if I execute it alone
        abc.push_back(obj->*newEvent); // Error c2298 here
    }

    static EventManager* Get();

private:
    std::vector<void(*)(Event)> eventsList;
};

这就是我所说的:

EventManager::Get()->subscribe("EventName", this, &TestClass::eventTest);

void ATideManager::eventTest(Event event)
{
    //Test
}

我对C ++和模板很陌生,所以我确信解决方案很简单,但我不明白为什么我可以调用该事件但不将其添加到向量中。你知道我怎么可能这样做吗?

2 个答案:

答案 0 :(得分:1)

obj->*newEvent无效。成员函数指针只能以这种方式用于调用指向成员函数。

但您可以使用std::vector<std::function<void(Event)>>

abc.push_back(std::bind(newEvent, obj, std::placeholders::_1);

std::bind reference

答案 1 :(得分:1)

正如documentation for that error message所说:

  

指向成员函数表达式的指针必须调用成员函数。

换句话说,你不能存储一个指向成员函数的指针,包括要调用它的对象,供以后使用。

以下是使用与您类似的名称的简单示例:

struct Object
{
    void f() {}
};

int main()
{
    Object obj;

    using member_function_pointer = void (Object::*)(); 

    member_function_pointer ptr = &Object::f;

    (obj.*ptr)();
    (obj.*ptr); // error
}

这很有道理。你的abc可能是成员函数指针的向量(或者只是函数指针的向量);它不能神奇地存储一个对象以及每个指针。

通常,指向成员函数的指针并不是C ++中最好,最干净或最好的特性,而且糟糕的语法使得使用它的每一段代码都完全不可读。幸运的是,C ++ 11引入了 std::function和lambdas ,这为您提供了更好的选择:

#include <functional>
#include <iostream>
#include <string>
#include <vector>

struct Event
{
    int i;
};

class EventManager
{
public:
    void subscribe(std::string const& eventName,
                   std::function<void(Event const&)> event)
    {
        abc.push_back(event);
    }

    static EventManager& get()
    {
        static EventManager instance;
        return instance;
    }

    void onEvent(Event const& event)
    {
        for (auto&& f : abc)
        {
            f(event);
        }
    }

private:
    EventManager() {}
    EventManager(EventManager const&) = delete;
    EventManager& operator=(EventManager const&) = delete;

    std::vector<std::function<void(Event const&)>> abc;

};

struct ATideManager
{
    void f()
    {
        EventManager::get().subscribe("EventName",
            [=](Event const& event) { eventTest(event); });
    }

    void eventTest(Event const& event)
    {
        std::cout << "eventTest: " << event.i << "\n";
    }
};

int main()
{
    ATideManager manager;
    manager.f();
    Event some_event{ 123 };
    EventManager::get().onEvent(some_event);
}

我还修复了你不必要地使用可以使用引用的指针,以及一些const - 正确性问题。