You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无法在std::map中正确存取GameState对象,多态调用失效求助

问题原因分析

你的问题核心是对象切片(Object Slicing),这是C++处理多态时极易踩中的坑。

看这段关键代码:

gameStates.insert(std::make_pair(name, *state));

你把传入的GameState*指针解引用后,直接将子类对象(比如MainMenuState)赋值给了std::map里的GameState父类对象。此时子类特有的成员变量、虚函数表信息都会被"切掉",map最终存储的只是一个纯粹的GameState父类副本,完全丢失了子类的多态特性。

后续从map中取出对象赋值给nextState和currentState时,拿到的依然是被切片后的父类对象,所以调用HandleInput()、Update()、Draw()这些虚函数时,只会执行父类的默认实现,永远触发不了子类的重写版本。

解决思路

要保留多态特性,你需要在map中存储**指针(或智能指针)**而非对象本身,这样才能通过指针的动态绑定,正确调用子类的虚函数实现。

1. 修改容器类型

把gameStates改成存储智能指针(推荐用std::unique_ptr,自动管理内存,避免泄漏):

std::map<std::string, std::unique_ptr<GameState>> gameStates{};

2. 更新AddGameState方法

调整插入逻辑,直接存储子类对象的指针(用智能指针接管内存):

void GameStateManager::AddGameState(std::string name, GameState* state) {
    // 用unique_ptr接管传入的state内存,无需手动释放
    gameStates.emplace(std::move(name), std::unique_ptr<GameState>(state));
    // C++14及以上更推荐用make_unique直接创建对象,避免裸指针传递:
    // gameStates.emplace(std::move(name), std::make_unique<MainMenuState>());
}

3. 修改状态切换相关代码

把nextState和currentState也改成智能指针类型,确保调用虚函数时触发动态绑定:

// 在GameStateManager类中声明成员变量
std::unique_ptr<GameState> nextState;
std::unique_ptr<GameState> currentState;

void GameStateManager::SetNext(std::string name) {
    auto it = gameStates.find(name);
    if (it != gameStates.end()) {
        // 如果需要每个状态是独立实例,建议给GameState加纯虚Clone方法:
        // nextState = it->second->Clone();
        // 如果共享同一个实例,直接赋值即可:
        nextState = it->second;
    }
}

void GameStateManager::SwitchState() {
    currentState = std::move(nextState);
}

4. 调用虚函数的调整

现在currentState是智能指针,调用成员函数时需要用->:

currentState->HandleInput();
currentState->Update();
currentState->Draw();

额外提示

  • 如果状态对象需要多次复用,建议给GameState类添加纯虚的Clone()方法,每次切换状态时创建子类对象的新副本,避免共享实例导致的状态混乱。
  • 尽量避免裸指针,优先用std::unique_ptr或std::shared_ptr管理内存,减少内存泄漏风险。

内容的提问来源于stack exchange,提问作者Caedendi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:36:19