如何将类成员函数作为函数指针传入StateMachine的addState方法
问题描述
想在自定义的MyStateMachine类中使用StateMachine类,但不想继承它,仅通过调用其函数封装逻辑。
现有代码
MyStateMachine.h
#include <StateMachine.h> class MyStateMachine { public: void Initialisation(); private: StateMachine machine = StateMachine(); State* m0Initialisation = machine.addState(&Initialisation); // 此处报错 };
MyStateMachine.cpp
#include "MyStateMachine.h" void MyStateMachine::Initialisation() { // 初始化操作逻辑 }
函数声明与编译错误
StateMachine::addState的声明为:
State* addState(void (*functionPointer)());
编译时触发错误:
error: no matching function for call to 'StateMachine::addState(void (MyStateMachine::*)()) note: State* StateMachine::addState(void (*)()) State* addState(void (*functionPointer)()); note: no known conversion for argument 1 from 'void (MyStateMachine::*)()' to 'void (*)()' Compilation error: no matching function for call to 'StateMachine::addState(void (MyStateMachine::*)())'
已知类成员函数依赖对象实例,无法直接转换成普通函数指针;若将Initialisation定义在类外则可正常传入指针。现需解决:不借助外部库(如std::bind)的情况下,如何将类成员函数传入addState?
解决方案
核心逻辑是用静态成员函数做中转,结合类实例指针完成成员函数的间接调用,绕过普通函数指针与成员函数指针的类型不兼容问题。
实现步骤
- 添加静态成员变量保存
MyStateMachine的实例指针 - 编写静态中转函数,通过实例指针调用目标成员函数
- 将静态中转函数传入
addState,同时调整成员初始化顺序避免未定义行为
修改后的代码
MyStateMachine.h
#include <StateMachine.h> class MyStateMachine { public: MyStateMachine() { // 构造函数中保存当前实例指针 s_instance = this; // 移至构造函数初始化状态,避免成员初始化顺序问题 m0Initialisation = machine.addState(&StaticInitialisation); } void Initialisation(); private: static MyStateMachine* s_instance; // 静态指针存储实例 static void StaticInitialisation(); // 静态中转函数 StateMachine machine; State* m0Initialisation; };
MyStateMachine.cpp
#include "MyStateMachine.h" // 初始化静态成员变量 MyStateMachine* MyStateMachine::s_instance = nullptr; void MyStateMachine::Initialisation() { // 初始化操作逻辑 } void MyStateMachine::StaticInitialisation() { // 通过静态指针调用目标成员函数 if (s_instance != nullptr) { s_instance->Initialisation(); } }
多实例场景优化(可选)
如果MyStateMachine需要支持多实例,静态指针会导致冲突。若能修改StateMachine源码,可扩展addState支持上下文参数:
// 修改StateMachine的addState声明 State* addState(void (*functionPointer)(void*), void* context);
对应调整中转函数与调用逻辑:
// 静态中转函数改为带上下文参数 static void StaticInitialisation(void* context) { MyStateMachine* instance = static_cast<MyStateMachine*>(context); instance->Initialisation(); } // 构造函数中传入当前实例作为上下文 m0Initialisation = machine.addState(&StaticInitialisation, this);
内容的提问来源于stack exchange,提问作者Marco Fuchs
相关产品推荐
相关产品推荐

