问题描述
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
时,我得到:
解决方法
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*&
参数使用 item
假定 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
元素的直接引用,那么我建议使用 {{1 }} 返回旧的 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;
}