- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
所以我正在开发一个基于文本的角色扮演游戏,但我遇到了一个问题。我目前正致力于从角色的库存中装备武器。我正在努力做到这一点,以便我的程序可以判断他们想要装备的元素是否属于 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;
现在,Weapon
是 Item
的子类,这就是我使用动态转换的原因——试图改变 chosenWeapon
, 类型为 Item
, 输入 Weapon
为了比较这两个类。 (我在 or 中使用这些 cout<<
来测试从这些对象调用函数是否有效)。
我的程序可以编译,并且一切正常,直到我们到达 maybeWeapon->getName()
,其中程序崩溃。我已经研究了很多,但我只是不明白我做错了什么。非常感谢任何答案或替代建议!谢谢!
最佳答案
问题是您尝试对 Weapon
进行动态转换,但实际上指向的对象是一个真正的拷贝构造的 Item
而不是子类。当您取消引用时,这会导致 nullptr
和 UB!
假设您的 list 中只有 Weapon
对象。代码段中的第一条指令是罪恶的根源:
Item tempChosenWeapon = myInventory.chooseItem();
这是声明是Item
对象的复制构造。如果源对象是 Weapon
,它将是 sliced .
稍后您获取指向此对象的指针:
Item *chosenWeapon = &tempChosenWeapon;
但是这个 Item*
并没有像你想象的那样指向一个 Weapon
对象。它指向一个真正的原始 Item
对象!因此,当您在此处进行动态转换时:
Weapon *maybeWeapon = dynamic_cast<Weapon*>(chosenWeapon);
代码会发现 choosenWeapon
不是 Weapon*
,dynamic_cast
的结果将是 nullptr
。到目前为止,这不一定是一场灾难。但是当你随后取消引用这个指针时,你会得到 UB:
maybeWeapon->getName() // OUCH !!!!!!
检查 dynamic_cast
是否成功(即结果不是 nullptr
)是防止崩溃的保护措施,但不会解决您的根本问题。
问题甚至可能比预期的更深:myInventory.chooseItem()
实际上返回什么类型?它是一个普通的 Item 吗?那么您的库存中可能已经存在切片问题!
如果要使用多态:
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;
如果这仍然无效,那么您的库存容器可能存在缺陷。在这种情况下,请查看 this question在使用您的容器代码打开一个单独的问题之前
关于c++ - 多态性和动态转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51974105/
我来自 Asp.Net 世界,试图理解 Angular State 的含义。 什么是 Angular 状态?它类似于Asp.Net中的ascx组件吗?是子页面吗?它类似于工作流程状态吗? 我听到很多人
我一直在寻找 3 态拨动开关,但运气不佳。 基本上我需要一个具有以下状态的开关: |开 |不适用 |关 | slider 默认从中间开始,一旦用户向左或向右滑动,就无法回到N/A(未回答)状态。 有人
我是一名优秀的程序员,十分优秀!