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

OOP场景下如何调用容器中实际对象的成员函数?

问题分析与修复方案

嘿,你的问题其实很典型——你在Killer::inActionRoom()里不小心创建了目标玩家的副本,而不是直接操作原对象。当你执行chosenPlayerForFight.decreasePoints()时,只是改了栈上的临时副本,房间里真正的玩家对象根本没被触动,这就是为啥日志里点数看起来每次都在重置的原因。

核心修复步骤

1. 把副本改成引用

直接修改Killer::inActionRoom()里的对象获取代码:

// 原来的错误代码:创建了副本
Player chosenPlayerForFight = *it;

// 修改为:获取原对象的引用
Player &chosenPlayerForFight = *it;

这样chosenPlayerForFight就绑定到了房间玩家列表里的真实对象上,后续调用decreasePoints()就会直接修改原玩家的点数了。

2. 确认返回的是正确的引用

另外要确保Room::getPlayersWithoutKillers()确实返回的是std::vector<Player>&(不是值类型),从你给的代码片段看这部分是对的,但如果这个方法返回的是值的话,哪怕用了引用也会绑定到临时对象上,这点要留意。

额外的线程安全提醒

因为你的玩家都是以线程方式运行的,操作共享的房间玩家列表时一定要注意线程安全。比如在获取玩家列表、选择目标、修改点数的整个过程中,应该用互斥锁保护起来,避免数据竞争。比如可以给Room类加个成员互斥锁,或者用你已经定义的globalMessageMutex:

// 假设Room类有一个std::mutex成员roomMutex,提供getMutex()方法获取
std::lock_guard<std::mutex> roomLock(room->getMutex());

std::vector<Player> &playersWithoutKillers = room->getPlayersWithoutKillers(); 
auto it = playersWithoutKillers.begin(); 

// 别忘了判断容器是否为空,避免访问end()迭代器崩溃
if (it != playersWithoutKillers.end()) {
    Player &chosenPlayerForFight = *it;
    int before = chosenPlayerForFight.getPoints();
    chosenPlayerForFight.decreasePoints();
    
    // 输出日志也要加锁,避免多线程输出乱序
    std::lock_guard<std::mutex> msgLock(globalMessageMutex);
    std::cout << "-> Killer in " << room->getName() << " " << getName() 
              << " vs " << chosenPlayerForFight.getName() 
              << " Starting decreasing points from " << before 
              << " Ending decreasing points from " << chosenPlayerForFight.getPoints() << std::endl;
}

修复后的预期效果

修改完成后,你应该能在日志里看到普通玩家的点数持续递减,比如第一次战斗后从1变成0,第二次变成-1,而不是每次都回到1的初始值了。

内容的提问来源于stack exchange,提问作者George P.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 06:49:07