C++如何在.so共享库中运行时修改类成员函数的指向?
报错原因
C++中普通类成员函数不是可修改的左值,无法直接赋值替换;且成员函数调用时会隐含传递this指针作为参数,你定义的普通无参函数getInput2和成员函数的签名本身不匹配,因此触发报错。
最简实现方案
方案1:修改原DoorTerminal类,用std::function实现动态替换(推荐)
这种方式灵活性最高,支持运行时任意修改实现逻辑:
- 首先修改
DoorTerminal类的定义:
#include <functional> #include <string> // 其他原有的头文件引用按需保留 class DoorTerminal : public DialogueInterfacing { // 其他原有成员定义保持不变 public: DoorTerminal(DialogueBox *dialogue_, Door* door_); // 将原普通成员函数改为std::function成员 std::function<void()> getInput; private: Door* door; // 把原来的默认逻辑抽成私有成员函数 void defaultGetInput() { std::string input = dialogue->getInput(); if(input == "1234"){ door->unlock(); } } };
- 对应修改构造函数的实现,初始化
std::function绑定默认逻辑:
DoorTerminal::DoorTerminal(DialogueBox *dialogue_, Door* door_): DialogueInterfacing(dialogue_), door(door_){ emptyFor.push_back(std::string("Player")); type.push_back(std::string("DoorTerminal")); type.push_back(std::string("DialogueInterfacing")); imgpath = "/vagrant_data/Skeleton-game/src/sprites/terminal.png"; typestring = "DoorTerminal"; // 绑定默认实现 getInput = [this](){ defaultGetInput(); }; }
- 在.so中替换逻辑的写法:
#include <iostream> // 其他头文件按需保留 // 替换为你实际的dialogue实例指针和door实例指针 DoorTerminal* doorTerminal = new DoorTerminal(dialogue_ptr, door_ptr); // 自定义实现,用lambda捕获实例指针即可访问实例内部成员 doorTerminal->getInput = [doorTerminal](){ std::string input = "EE"; if(input == "1234"){ std::cout << "hello" << std::endl; // 如需访问实例的door成员直接写doorTerminal->door即可 } }; // 调用时直接执行即可 doorTerminal->getInput();
方案2:继承重写(无需修改原类定义,前提是原getInput为虚函数)
如果不能修改原DoorTerminal的代码,且原类的getInput有virtual修饰符,直接子类重写即可:
class CustomDoorTerminal : public DoorTerminal { public: // 继承父类的构造函数 using DoorTerminal::DoorTerminal; // 重写getInput逻辑 void getInput() override { std::string input = "EE"; if(input == "1234"){ std::cout << "hello" << std::endl; } } }; // 创建实例时直接创建子类实例即可 DoorTerminal* doorTerminal = new CustomDoorTerminal(dialogue_ptr, door_ptr);
内容的提问来源于stack exchange,提问作者Michael
相关产品推荐
相关产品推荐

