Lit*_*lue 2 c++ polymorphism software-design game-development game-engine
所以我正在研究一个基于文本的RPG,我遇到了一个问题.我目前正在从角色的库存中装备武器.我试图这样做,以便我的程序可以判断他们想要装备的物品是否属于等级Weapon.这是相关代码的剪辑:
Item tempChosenWeapon = myInventory.chooseItem();
cout << tempChosenWeapon.getName() << endl;
Item *chosenWeapon = &tempChosenWeapon;
cout << chosenWeapon->getName() << endl;//THE CODE WORKS UP TO HERE
Weapon *maybeWeapon = dynamic_cast<Weapon*>(chosenWeapon);
cout << maybeWeapon->getName() << endl;
Run Code Online (Sandbox Code Playgroud)
现在,Weapon是一个子类Item,这就是为什么我使用动态强制转换 - 尝试更改chosenWeapon(类型)Item,Weapon以便比较两个类.(我正在使用这些cout<<或测试是否从这些对象调用函数).
我的程序编译,一切运行正常,直到我们来到maybeWeapon->getName()程序崩溃.我已经研究了很多,但我只是不明白我做错了什么.任何答案或替代建议非常感谢!谢谢!
问题是你尝试动态转换为a Weapon但实际上指向的对象是构造的真实副本Item而不是子类.nullptr当你取消引用它时,这会导致a 和UB!
假设Weapon您的库存中只有对象.你的片段中的第一条指令是你邪恶的根源:
Item tempChosenWeapon = myInventory.chooseItem();
Run Code Online (Sandbox Code Playgroud)
这是声明是Item对象的复制构造.如果源对象是a Weapon,它将被切片.
稍后你会得到一个指向这个对象的指针:
Item *chosenWeapon = &tempChosenWeapon;
Run Code Online (Sandbox Code Playgroud)
但是这Item*并没有Weapon像你想象的那样指向一个物体.它指向一个真正的粗糙Item对象!所以当你在这里进行动态转换时:
Weapon *maybeWeapon = dynamic_cast<Weapon*>(chosenWeapon);
Run Code Online (Sandbox Code Playgroud)
代码将发现choosenWeapon不是a Weapon*,结果dynamic_cast将是a nullptr.到目前为止,它不一定是灾难.但是当你然后对这个指针进行反驳时你会得到UB:
maybeWeapon->getName() // OUCH !!!!!!
Run Code Online (Sandbox Code Playgroud)
检查是否dynamic_cast成功(即结果不是nullptr)是防止崩溃的保护,但不能解决您的根本问题.
问题甚至可能比预期的更深:myInventory.chooseItem()现实中的回报是什么类型?这是一个简单的项目吗?那么你可能已经在库存中出现了切片问题!
如果你想使用多态:
Item:您需要调用多态clone()函数并确保此克隆的目标具有兼容类型. 从解决方案开始,它是这样的:
Item* chosenWeapon = myInventory.chooseItem(); // refactor choosItem() to return a pointer.
cout << chosenWeapon->getName() << endl;
Weapon *maybeWeapon = dynamic_cast<Weapon*>(chosenWeapon);
if (maybeWeapon)
cout << maybeWeapon->getName() << endl;
else cout << "Oops the chosen item was not a weapon" <<endl;
Run Code Online (Sandbox Code Playgroud)
如果这仍然不起作用,那么您的库存容器将存在缺陷.在这种情况下,请在使用容器代码打开单独的问题之前查看此问题
| 归档时间: |
|
| 查看次数: |
182 次 |
| 最近记录: |