2016-08-04 143 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(); 
}