不知道从哪里开始

时间:2016-08-04 09:17:46

标签: c++ class inheritance casting downcast

所以只需建立一个物品和库存/装备系统。

我这样做的解决方案是拥有一个基础Item类,然后是MeleeWeapon,RangedWeapon等子类,它们将附加更多特定的值和函数。

我的问题在这里:

unsigned int Player::equipItem(Item item)
{
    //first, we equip the item
    switch (item.subClass) {
    case SC::MELEE_WEAPON :
        if (item.isOneHanded) {
            //unequip mainhand (returns 2! so we can see if something was already there, equip mainhand slot.
            //blabla
            return 1; // yay!
        }
        break;
    case SC::RANGED_WEAPON :
        break;
    case SC::SHIELD :
        break;
    case SC::ARMOR :
        break;
    }
    return 0; //somethings fucked up.
}

所以,错误是第6行,这是因为item没有isOneHanded,但是MeleeWeapon没有。这在运行时是安全的99.9999%肯定,但编译器不知道。我在某个地方看到你可以动态地将它动态地投射到MeleeWeapon上,然后我玩了它,得到了更多令人困惑的错误,并且一直持续。

SC :: ...正是我用来识别项目的子类的。

至于我正在寻找的解决方案类型:

尽可能简单,尽可能多的解释。我想学习不复制粘贴!谢谢!

3 个答案:

答案 0 :(得分:0)

您必须将item转换为实际类型。为此,请使用dynamic_castdynamic_cast检查运行时是否允许您将item转换为实际类型。如果item可以转换为你想要的,它返回一个正确的指针,如果没有,它返回空指针(如果是动态转换指针 - 在引用转换的情况下,它会抛出异常)。它只适用于虚拟类。

case SC::MELEE_WEAPON :
{ // Brace are required here to allow declaration of local melee
    MeleeWeapon * melee = dynamic_cast<MeleeWeapon *>(&item);
    if (melee) // If cast has succeed
    {
        if (melee.isOneHanded) {
            //unequip mainhand (returns 2! so we can see if something was already there, equip mainhand slot.
            //blabla
            return 1; // yay!
        }
    }
    break;
}
case SC::RANGED_WEAPON :
{
    RangedWeapon * ranged = dynamic_cast<RangedWeapon *>(&item);
    if (ranged) // If cast has succeed
    {
    break;
}
//.... and so on

如果你使用C ++ 11,你也可以用以下代码替换动态转换的行:

auto melee = dynamic_cast<MeleeWeapon *>(&item);

答案 1 :(得分:0)

如果你100%确定Item是MeleeWeapon类型,那么你可以使用upcast。 否则你可以使用动态强制转换来解决这个问题。

unsigned int Player::equipItem(Item item)
{
    //first, we equip the item
    switch (item.subClass) {
    case SC::MELEE_WEAPON :
        MeleeWeapon * weapon = dynamic_cast<MeleeWeapon *>(&item);
        if(weapon != nullptr)
        {
          if (weapon->isOneHanded) {
               //unequip mainhand (returns 2! so we can see if something was already there, equip mainhand slot.
            //blabla
            return 1; // yay!
          }
        }
        else //this item is not a MeleeWeapon 
        {
        }
        break;
    case SC::RANGED_WEAPON :
        break;
    case SC::SHIELD :
        break;
    case SC::ARMOR :
        break;
    }
    return 0; //somethings fucked up.
}

答案 2 :(得分:0)

您有一个Item函数,并希望返回unsigned int,具体取决于Item的类型(和其他属性)。

您可以使用dynamic_cast 提供的 MeleeWeapon(和其他项目)继承自Item(并由其他答案建议)。

对我来说,使用多态而不是切换更有意义。

class Item
{
public:
    virtual ~Item() = 0;//don't forget this
    virtual unsigned int equip() const
    {
        return 0;
    }
};

class MeleeWeapon : public Item //you do have this already, right?
{
public:
    MeleeWeapon(bool oneHanded) : oneHanded(oneHanded) 
    {
    }
    virtual unsigned int equip() const
    {
        return oneHanded ? 1 : 0;
    }
private:
    bool oneHanded;
};

class Player
{
public:
    unsigned int equipItem(const Item & item);//note the signature change
};

unsigned int Player::equipItem(const Item & item)
{
    return item.equip();
}