I am currently trying to wrap my head around how to actually work with derived / inherited classes, how to set up a little "tree" of such classes and how to store and access them in a vector.
Like for a game where the player can have different types of items in their inventory but they are all stored in one vector and not a bunch of vectors for each item type.
I know you can do this with a vector of pointers to the base object and then use dynamic_cast to cast the pointers to be pointers to objects of the appropriate class.
I know that you have to be VERY careful with this and you have to make a second vector that keeps track of what object type is stored at which index to cast them properly.
My question is:
What is the proper way of implementing something like this?
I have read "don't do the dynamic cast thing" online but just saying "don't do this" without an alternate or better solution is not really useful ...
Here is a little example of what I am trying to implement:
(Without boundschecking, without type checking for the casting, just to get across what I want to do)
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 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
|
#include <iostream>
#include <vector>
#include <string>
#include <memory>
using namespace std;
//START OF ITEM CLASSES
class Item{
public:
string Name; //Each item has a name, no matter what type of item it is
float Value; //Each item has a value when buying or selling it
void Use(void)
{
//Default function that gets called if no actual use function is implemented (if this does not get overloaded)
cout << "Can't use this item" << endl;
}
};
class Tool: public Item{
public:
float DamagedState; //Tools get damaged over time when used
//No overloaded "Use" function here because there won't be any actual objects of this class, but functions might take objects of this type as parameters
Tool(void)
{
}
};
class Hammer: public Tool{
public:
Hammer(void)
{
Name = "Hammer";
}
virtual void Use(void)
{
cout << "Hammertime!" << endl;
DamagedState = DamagedState - 0.1;
}
};
//END OF ITEM CLASSES
class Person{
public:
string Name;
vector<unique_ptr<Item>> Inventory;
Person(string CName)
{
Name = CName;
}
void UseTool(Tool ToolToUse)
{
//ToolToUse can be something from the players inventory or something from the gameworld
cout << Name << " is now using " << ToolToUse.Name << endl;
ToolToUse.Use();
ToolToUse.DamagedState = ToolToUse.DamagedState - 0.1;
}
void PickUpItem(Item ItemToPickUp)
{
//Could be any item: a tool, a piece of clothing, a weapon, a food item, ...
//Or is it better to make like ten different overloaded functions, one for each type of item, so like PickUpItem(Tool ItemToPickUo) PickUpItem(Clothing ItemToPickUp) ... ?
Inventory.push_back(????????); //How do I push back any object? First cast them to a pointer to the base object?
}
Item DropItem(int IndexOfItemToDrop)
{
//Removes an item from the players inventory and retuns it (the returned object will be added to a vector of items on the ground or whatever)
//The main concept I need to figure out for this is how to return an item of any sub class
return ??? Inventory[IndexOfItemToDrop] ???;
}
};
int main()
{
Person Player("Player"); //There is a person object called "Player"
Hammer MyOldHammer(); //There is a hammer object called MyOldHammer
Player.PickUpItem(??? MyOldHammer ???); //Adding the Hammer object to the players inventory, but I need to cast it somehow first?
Player.UseTool(??? Player.Inventory[0] ???); //How do I retreive a certain index from the vector like Player.Inventory[i] dereference it and then cast it to be a "Tool" object?
vector<unique_ptr<Item>> ItemsOnTheGround;
ItemsOnTheGround.push_back(??? Player.DropItem[0] ???); //Again, adding any object derived from the base objec
return 0;
}
| |