如何在 C++ 中交换父指针和子指针?

How can I swap a parent pointer and a child pointer in c++?

Weapon 继承自 Item.

weapon 是 class 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 时,我得到:

no matching function for call to 'swap(Item*&, Item*)'

std::swap() 将非常量左值引用作为输入,这就是为什么当您尝试与 static_cast<Item*>(weapon) 交换时出现“无匹配函数”错误的原因,这不是 [=66] =]ing 一个可以交换的左值。

为了将新的 item 分配给 weapon 成员,您需要 dynamic_cast return 的 Weapon* 指针,因此您的 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);

如果传递给 equip()item 不是对 inventory 元素的 直接 引用,那么我会建议使用 equip() return 旧的 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);