2016-08-04 100 views
0

所以只需建立一个物品和库存/装备系统。不知道从哪里开始

我这样做的解决方案是有一个基本的物品类,然后像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行,这是因为项目没有isOneHanded,但MeleeWeapon一样。这在运行时肯定会安全99.9999%,但编译器不知道。我看到了一个地方,你可以动态地将它投掷到一个MeleeWeapon手动和我一起玩,更容易混淆的错误,等等。

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

至于那种解决方案,我在寻找:

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

+0

您必须先放下 - 然后访问子类字段。目前你正在测试它适合什么类 - 然后你不投。 –

+1

*我看到了一个地方,你可以动态地将它移动到一个MeleeWeapon手动,我玩了,更容易混淆的错误,等等。*你尝试了什么,你有什么错误? – Ryan

+1

如果你知道你想使用'Item'那么为什么不是项目中的'isOneHanded'?事实上,一个更好的设计是不使用'subClass'成员来说明什么类型,并打开它。为什么不在项目中使用虚拟'equip'方法,然后根据实际的项目类型让它返回所需的任何内容? – doctorlove

回答

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); 
0

,如果你是100%肯定项的类型MeleeWeapon,那么你可以使用向上转型。 或者你可以使用动态转换来解决这个问题。

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. 
} 
0

你有一个函数获取Item和希望取决于Item的类型(和其他属性)返回一个unsigned int

你可以使用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(); 
}