I have a class Item
, and there are two classes derived from it Sword
and Shield
.
I want my player
to have an array of items:
class Item
{
int x;
};
class Sword : public Item
{
int sharpness = 10;
};
class Shield : public Item
{
int blockChance = 2;
};
class player
{
Item* items[4];
player()
{
items[0] = new Sword;
items[1] = new Sword;
items[2] = new Shield;
items[3] = new Shield;
}
};
Is there a way I can access values of Sword
or Shield
from items
, for example:
items[2]->blockChance;
without having a separate array of Sword
s and Shield
s
If this is not possible, then I would just have a separate array of each, but a single array containing both would make this much easier
In order to access the properties of a derived class via the base class, you can add a virtual method. This is a method a derived class can override to provide a different implementation. If the base class has no meaningful implementation for it, it can also be abstract (AKA pure-virtual), which will force the derived class to implement it.
There are several other issues you should be aware of:
When dealing with inheritance and virtuals method, it is important to have a virtual destructor in the base class. Otherwise the destructor of the derived classed will not be invoked when they are access via a pointer/reference (even if in your toy example this is not relevant, it's a good practice).
Instead of using raw C arrays, you should favor std::array
for static sized arrays, and std::vector
for dynamic sized ones.
Instead of using raw pointers with manual new
/delete
, you should use smart pointers: std::unique_ptr
(the default), or std::shared_ptr
(if shared ownership is required).
You can use a member initialization list to init items
in the constructor of class Player
.
The complete solution is demonstrated below:
#include <array> // for std::array
#include <memory> // for std::unique_ptr
#include <iostream> // for std::cout etc.
class Item
{
public:
virtual ~Item() {} // important to add a virtual destructor
virtual int GetProperty() = 0; // a virtual method for accessing the property
};
class Sword : public Item
{
int sharpness = 10;
public:
int GetProperty() override { return sharpness; } // override of the virtual method
};
class Shield : public Item
{
int blockChance = 2;
public:
int GetProperty() override { return blockChance; } // override of the virtual method
};
class Player
{
std::array<std::unique_ptr<Item>, 4> items; // use std::array instead of a raw C array (or std::vector for a dynamic array),
// and std::unique_ptr instead of a raw poniter.
public:
Player()
: items{ std::make_unique<Sword>(),
std::make_unique<Sword>(),
std::make_unique<Shield>(),
std::make_unique<Shield>() } // use a member initialization list
{}
std::array<std::unique_ptr<Item>, 4>& GetItems() { return items; }
};
int main()
{
Player player;
std::cout << player.GetItems()[0]->GetProperty() << '\n'; // access the Sword property
std::cout << player.GetItems()[2]->GetProperty() << '\n'; // access the Shield property
}
Output:
10
2