具有不同类的类函数的函数指针数组

时间:2018-01-21 13:04:52

标签: c++ pointers function-pointers

SomeClass.h

class SomeClass{
    public:
        static std::vector<void (*)()> UpdateFuncs;
}

OtherClass.h

class OtherClass{
    private:
        void Update();
    public:
        OtherClass();
}

OtherClass.cpp

OtherClass::OtherClass(){
    Time::UpdateFuncs.push_back(&(this->Update));
}

On Build我对绑定成员函数表达式进行'&':非法操作 如果我这样做:

.push_back(&Update);

然后我得到“没有重载函数的实例

  

std :: vector&lt; _Ty,_Alloc&gt; :: push_back [with _Ty = void(*)(),_ Alloc = std :: allocator]“匹配参数列表”

提前感谢

2 个答案:

答案 0 :(得分:1)

OtherClass::Update不适合void (*)()函数指针,因为它是非静态成员函数;就好像它有一个“不可见的”OtherClass*参数。

使用std::function来实现目标:

#include <functional>

class Time
{
public:
    static std::vector<std::function<void()>> UpdateFuncs;
};

在OtherClass.cpp中,使用this - 捕获lamba作为函数对象:

OtherClass::OtherClass()
{
    Time::UpdateFuncs.push_back([this] { Update(); });
}

当然,如果您将Update设为静态,那么您仍然可以使用void (*)(),因为“隐身”参数已删除,但std::function只是安全而现代的方式。

答案 1 :(得分:0)

问题

您尝试为void(*)()类型的普通函数指针指定类型为void(OtherClass::*)()的成员函数指针。

不幸的是,这两种类型是不兼容的:只能使用其参数调用普通函数,并且只能为特定对象调用成员函数指针。

第一个解决方案:成员函数指针

您必须更改向量的定义以使其使用成员函数指针。

class OtherClass;  // forward deaclaration
class SomeClass {
public:
    static std::vector<void (OtherClass::*)()> UpdateFuncs;
};

然后你可以按预期推回函数:

OtherClass::OtherClass() {
    SomeClass::UpdateFuncs.push_back(&OtherClass::Update);
}

Online demo

不幸的是,你不能将它与成员函数指针混合到其他类或普通函数指针。并且您必须在调用函数时指定要使用的对象。

更好的解决方案:命令模式

command pattern 可让您比功能指针更灵活。由于命令的专业化,您可以混合将调用普通函数指针,不同类的成员函数指针或ad-hoc函数的命令。

命令可能如下所示:

class Command {
public: 
    virtual void execute() = 0; 
    virtual ~Command();
}; 

class CommandOtherClass : public Command { 
    OtherClass *target; 
    void (OtherClass::*f)(); 
public: 
    CommandOtherClass (void (OtherClass::*fct)(), OtherClass*t); 
    void execute() override; 
};

实施非常简单:

CommandOtherClass::CommandOtherClass (void (OtherClass::*fct)(), OtherClass*t) 
    :  f(fct),target(t) 
{
} 
void CommandOtherClass::execute() {
    (target->*f)();
}

SomeClass函数可以更改如下:

class SomeClass {
public:
    static std::vector<unique_ptr<Command>> UpdateFuncs;
    static void executeAll();
};

请注意,您可以开发它以包含注册和取消注册功能,这样您也可以从涉及不再存在的对象的矢量命令中删除它。

向矢量添加新命令将如下所示:

OtherClass::OtherClass() {
    SomeClass::UpdateFuncs.push_back(make_unique<CommandOtherClass>(&OtherClass::Update, this));
}

最后,这里有一个完整的 online demo ,可以调用为某些本地对象自动注册的两个命令,甚至可以添加与任何其他对象无关的第三个ad hoc命令。