InSomeClass.h
class SomeClass{
public:
static std::vector<void (*)()> UpdateFuncs;
}
InOtherClass.h
class OtherClass{
private:
void Update();
public:
OtherClass();
}
在其他类中.cpp
OtherClass::OtherClass(){
Time::UpdateFuncs.push_back(&(this->Update));
}
在构建时'&':
我对绑定成员函数表达式进行了非法操作 如果我这样做:
.push_back(&Update);
然后我得到"没有重载函数的实例
std::vector<_Ty, _Alloc>::p ush_back [with _Ty=void (*)(), _Alloc=std::allocator]" 匹配参数列表">
提前致谢
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
只是安全和现代的方法。
问题
您尝试分配给类型的普通函数指针void(*)()
void(OtherClass::*)()
类型的成员函数指针。
不幸的是,这两种类型是不兼容的:普通函数只能用其参数调用,成员函数指针只能为特定对象调用。
第一个解决方案:成员函数指针
您必须更改向量的定义以使其使用成员函数指针。
class OtherClass; // forward deaclaration
class SomeClass {
public:
static std::vector<void (OtherClass::*)()> UpdateFuncs;
};
然后,您可以按预期回推函数:
OtherClass::OtherClass() {
SomeClass::UpdateFuncs.push_back(&OtherClass::Update);
}
在线演示
遗憾的是,您不能将其与指向其他类或普通函数指针的成员函数指针混合使用。 并且您必须指定在调用函数时要使用的对象。
更好的解决方案:命令模式
命令模式比函数指针具有更大的灵活性。 由于命令的专用化,您可以混合调用普通函数指针、不同类的成员函数指针或即席函数的命令。
这些命令可能如下所示:
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));
}
最后,这里有一个完整的在线演示,它调用了为某些本地对象自动注册的两个命令,甚至添加了与任何其他对象无关的第三个临时命令。