c++ - 如何在 C++ 中交换父指针和子指针?
问题描述
Weapon
继承自Item
。
weapon
是类的成员Hero
。我想将它与item
传入的函数交换,这也是Weapon
本示例的一个(我将添加更多案例)。
void Hero::equip(Item* item){
if(instanceof<Weapon>(item)){std::swap (item, static_cast<Item>(weapon));}
}
基本上,当从英雄的物品栏中装备某物时,我希望它存储在 的相应成员中Hero
,item
而之前装备的物品将重新存储在物品栏中,无论物品类型如何。库存是一个std::vector<Item*>
,因此它可以容纳多态物品。
向上转换weapon
似乎不起作用,因为Item
是虚拟的。我尝试过的所有其他类型的铸造也失败了,一些手动交换它们的尝试也是如此。如果您想知道instanceof
,我复制了这个模板,以便可以在 C++ 中使用它:
template<typename Base, typename T>
inline bool instanceof(const T *ptr) {
return dynamic_cast<const Base*>(ptr) != nullptr;
}
当我使用Item*
而不是Item
,我得到:
调用 'swap(Item*&, Item*)' 没有匹配的函数
解决方案
std::swap()
将非常量左值引用作为输入,这就是为什么当您尝试与 交换时会收到“没有匹配函数”错误的原因static_cast<Item*>(weapon)
,这不会返回您可以交换的左值。
为了将新成员分配item
给weapon
成员,您需要返回的Weapon*
指针dynamic_cast
,因此您的instanceof()
模板在这里没有帮助您。
试试这个:
void Hero::equip(Item* &item) {
if (Weapon *new_weapon = dynamic_cast<Weapon*>(item)) {
Item *old_weapon = weapon;
weapon = new_weapon;
item = old_weapon;
}
}
或者:
void Hero::equip(Item* &item) {
if (Weapon *w = dynamic_cast<Weapon*>(item)) {
std::swap(weapon, w);
item = w;
}
}
或者,如果您使用的是 C++14 或更高版本,则可以std::exchange()
改用:
void Hero::equip(Item* &item) {
if (Weapon *new_weapon = dynamic_cast<Weapon*>(item)) {
item = std::exchange(weapon, new_weapon);
}
}
注意:Item*&
foritem
参数的使用假定使用直接取自元素的指针equip()
调用它,例如:Item*
inventory
hero.equip(hero.inventory[index]);
而不是间接的,像这样:
Item *item = hero.inventory[index];
hero.inventory.erase(hero.inventory.begin()+index);
hero.equip(item);
如果item
传入的equip()
不是直接引用的元素inventory
,那么我建议equip()
返回旧的Item*
并让调用者决定如何处理它,例如:
Item* Hero::equip(Item* item) {
if (Weapon *new_weapon = dynamic_cast<Weapon*>(item)) {
Item *old_weapon = weapon;
weapon = new_weapon;
return old_weapon;
}
...
return nullptr;
}
或者:
Item* Hero::equip(Item* item) {
if (Weapon *w = dynamic_cast<Weapon*>(item)) {
std::swap(weapon, w);
return w;
}
...
return nullptr;
}
或者:
Item* Hero::equip(Item* item) {
if (Weapon *new_weapon = dynamic_cast<Weapon*>(item)) {
return std::exchange(weapon, new_weapon);
}
...
return nullptr;
}
然后调用者可以做这样的事情:
Item *item = hero.inventory[index];
hero.inventory.erase(hero.inventory.begin()+index);
item = hero.equip(item);
if (item) hero.inventory.push_back(item);
推荐阅读
- docker - 无法连接到 docker 网络中的其他容器
- reactjs - 无法让 React JS 应用程序在 IE 11 中呈现
- java - android的问题:来自类的数据不发送到活动
- c++ - C++:保存来自特定实例的方法的函数指针
- javascript - 如何创建多个对象,每个对象都加载相同的页面但在javascript中具有不同的数据?
- python-3.x - 如何单击 iframe 中的元素
- sql - 为什么此 Access 报表编辑基础查询?
- android - 如何使用 Frida 读取堆上的内存?
- azure - 将 lucene 模糊搜索和同义词与 Azure 搜索结合使用
- r - 使用 gsub() 提取文件名的一部分