Please review my simple way of making a game inventory? Is it practical?

I'm working on a small side project for a class, but I am in a bit of a mix-up.

I got to the part of making an inventory where I have the derivative classes "Weapon", "Armor" and "Potion" (review code for better picture) and the base class that would be "Item". At least that was my original plan.

However, I wanted "Item" to be a class that could hold information of any item, be it a weapon, armor or potion, so that it would make an easy inventory on the main function (The inventory would then simply be an array of "Item" objects).

The following is my code, please read it and follow up on what I have to say. You could call it a "reverse-inheritance" or something.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
//Isn't my actual program, but wrote this to give a picture of the situation
#include <iostream>
#include <string>
using namespace std; //Yes. I went there.

//-----------------------------------------------------------------
//-----------------------------------------------------------------
class Weapon
{
   protected:
      int attack;
   public:
      Weapon(){}
      //Constructors,Get/Set, etc...
};

//-----------------------------------------------------------------
//-----------------------------------------------------------------
class Armor
{
   protected:
      int defense;
   public:
      Armor(){}
      //Constructors,Get/Set, etc...
};

//-----------------------------------------------------------------
//-----------------------------------------------------------------
class Potion
{
   protected:
      int potHeal;
   public:
      Potion(){}
      //Constructors,Get/Set, etc...
};

//-----------------------------------------------------------------
//-----------------------------------------------------------------
//Item class inherits from all the other classes, instead of the other way around
class Item:public Weapon, public Armor, public Potion
{
   protected:
      string itemName;
      string itemType;
   public:
      Item(){}
      //Constructors,Get/Set, etc...

};

int main()
{
   const int bagSize=25;

   Item inventory[bagSize];
}


The problem is, since "Item" inherits "Weapon", "Armor" and "Potion", it would have many unused variables. Suppose I wanted to make an item that is a weapon, for example, I would set something like the following:

1
2
3
inventory[0].setItemName("Iron Sword");
inventory[0].setItemType("Weapon");
inventory[0].setAttack(50);


But the weapon would have a variable of "defense" and "potHeal", which to me seems a bit messy, even if they are not used. Is there a better way of making my inventory? I just couldn't see it when I had "Item" as the base class.

Edited to resemble my program more, I have them as protected, not private.
Last edited on
I may be misunderstooding your question, just say if i am wrong :

But the weapon would have a variable of "defense" and "potHeal"


No it woudn't, potHeal and defense are declared inside private access and thus Item class will NOT inherit it, a derived class can only inherit public and protected members of the base class

EDIT

But the weapon would have a variable of "defense" and "potHeal"


No it wouldn't also, you did not make any of them inherit
Last edited on
Personally, unless I'm using interface classes (which you aren't), I much prefer to avoid multiple inheritance. The way I would think of doing this is to have an a collection of variables that is common for all items stored in the "Item" class, and then inherit data from that.

Here is a quick example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
class Item {
    public:
        enum ItemType {
            WEAPON,
            POTION,
            ARMOUR,
            INVALID,
        };
        
    protected:
        Item() 
            : _type(INVALID), _name("N/A") 
        {}

        Item(ItemType type, std::string name = "")
            : _type(type), _name(name)
        {}
        
        std::string _name;

    private:
        ItemType _type;
};

class Weapon : public Item {
    public:
        Weapon()
            : Item(ItemType::WEAPON)
        {}

    protected:
        int _attack;
};

class Potion : public Item {
    public:
        Potion ()
            : Item(ItemType::POTION)
        {}

    protected:
        int _heal;
};

class Armour : public Item {
    public:
        Armour ()
            : Item(ItemType::ARMOUR)
        {}

    protected:
        int _attack;
};

int main() {
    const int bagSize = 25;
    Item *inventory[bagSize];

    // Example Item
    Item *sword = new Weapon();
    inventory[0] = sword;
}


Something like that.
Last edited on
Ah, yes they are protected. Forgot to make that change on this program, will edit it in a sec.

However, if I do make them private, doesn't that mean I won't be able to access "attack" either? What would I be able to do with the function then, if the variable of attack is not inherited? What I mean to say is, would the variable "attack" exist at all in the instance of "Item" if it is private?
No, it wouldn't. Which is why I would do it the way I have above, due to being able to do something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// In the "Item" class, this is a public member
ItemType Item::getItemType(void) const {
    return _type;
}

// ...

int main() {
    const int bagSize = 25;
    Item *inventory[bagSize];

    inventory[0] = new Weapon;

    // Later...

    // Testing if the player wants to equip an item, and inventory
    // slot 0 has been selected
    if (shouldEquip && slot0->isSelected()) {
        switch(inventory[0]->getItemType()) {
            case WEAPON:
                player->equipWeapon(inventory[0]);
                std::cout << "Player equipped a weapon!" << std::endl;
            break;

            case ARMOUR:
                player->equipArmour(inventory[0]);
                std::cout << "Player equipped some armour!" << std::endl;
            break;

            default:
                std::cout << "You cannot equip that!" << std::endl;
        }
    }
}


EDIT:
Fixed Typo's
Last edited on
However, if I do make them private, doesn't that mean I won't be able to access "attack" either?


Yes, but you can declare them as friend class so you can access the private and protected members of another class
Yeah that looks like how I wanted to do it. However, I am unfamiliar with "enum" and so I am still studying your program trying to see how it works.
Topic archived. No new replies allowed.