I'm working on an inventory system for a game and I'm hitting a brick wall with object slicing; I'm losing variables on a reference to a derived class.
Below is an excerpt in which a T-shirt is created in the main game file, and then passed to a players inventory for storage. However only the variables present in the base class Item
are preserved.
game.cpp
#include "Item.h"
#include "Clothes.h"
#include "Shirts.h"
shirt_item white_shirt = shirt_item(materialDescriptor::cotton, colourDescriptor::white);
player.getComponent<InventoryComponent>().storeItem(&whiteShirt);
InventoryComponent.cpp
bool InventoryComponent::storeItem(Item *inItem)
{
if (freeInvSpace() > 0)
{
items.push_back(inItem);
return true;
}
else if (freeInvSpace() < 0)
{
std::cout << "ERROR! Inventory over filled somehow" << std::endl;
}
return false;
}
InventoryComponent.h
#pragma once
#include "Components.h"
#include "Item.h"
#include "Clothes.h"
#include "Shirts.h"
class InventoryComponent : public Component // Entity component system
{
public:
std::vector<Item*> items;
InventoryComponent(int inSize)
{
size = inSize;
}
bool storeItem(Item *inItem);
...
}
Item.h
#pragma once
#include <string>
class Item
{
public:
std::string name,
description;
bool pronoun;
};
Clothes.h
#pragma once
#include <vector>
#include <string>
#include "Item.h"
#include "materialDescriptor.h"
#include "colourDescriptor.h"
class Clothes : public Item
{
public:
materialDescriptor material;
std::vector<bodyParts> coverage;
colourDescriptor colour;
Clothes(std::string inName, std::string inDescription, materialDescriptor inMaterial, colourDescriptor colour, bool inPronoun = false)
{
name = inName;
description = inDescription;
material = inMaterial;
pronoun = inPronoun;
}
Clothes() {}
};
Shirts.h
#pragma once
#include "Clothes.h"
#include "materialDescriptor.h"
#include "colourDescriptor.h"
class shirt_item : public Clothes
{
public:
shirt_item(materialDescriptor inMaterial, colourDescriptor inColour)
{
material = inMaterial;
colour = inColour;
description = "A basic shirt that covers the wearer from the elements";
name = "T-Shirt"
}
}
ECS.h
#pragma once
#include <iostream>
#include <vector>
#include <memory>
#include <algorithm>
#include <bitset>
#include <array>
#include "Components.h"
class Component
{
public:
Entity* entity;
virtual void init() {}
virtual void update() {}
virtual void draw() {}
virtual ~Component() {}
private:
};
class Entity
{
private:
bool active = true;
std::vector<std::unique_ptr<Component>> components;
ComponentArray componentArray;
ComponentBitSet componentBitSet;
public:
template <typename T> T& getComponent() const
{
auto ptr(componentArray[getComponentTypeID<T>()]);
return *static_cast<T*>(ptr);
}
}
Using Vs2019 break points, the constructor for the T-shirt works but as soon as I attempt to use the object it is boiled down to it's base class: Item > Clothes > Shirts
If you pass and store inherited objects through pointers you eventually have to store them on the heap. Instead you are creating them on the stack. Just do
auto white_shirt = std::make_unique<shirt_item>(materialDescriptor::cotton, colourDescriptor::white);