1
class Component {
    // Code here
};

class TransformComponent : public Component {
    // Code here
};

class Entity:
    public:
        Component components[25];
        
        TransformComponent *getTransform() {
            for(int i = 0; i < 25; i++) {
                if(typeid(components[i]) == typeid(TransformComponent())) {return *(components + i);}
            }
        }
};

I have an array of components, and inside could be any child class of "Component", like "TransformComponent". The thing is, when compiling, the computer thinks that the components array is only populated with "Component" objects. The function is supposed to return a "TransformComponent", and the compiler sees that as an error, even though the element in the array I am returning is a TransformComponent. Is there any solution to this (preferably simple)?

Ranoiaetep
  • 5,872
  • 1
  • 14
  • 39
Keshav V.
  • 73
  • 7
  • One of the requirements of arrays in C++ is that every item in the array must have the same size (as returned by the `sizeof()` operator). This is a natural consequence of the way arrays are accessed -- i.e. to access the nth item in the array, the compiler will add `sizeof(Component)*n` to the memory address of the start of the array. But a subclass of `Component` will likely have a larger size than `Component` itself, since the subclass will likely have more member-variables than its superclass does. So subclasses of `Component` won't be able to fit into the slots provided by the array. – Jeremy Friesner Nov 17 '22 at 03:50
  • Btw if you try to force a `TransformComponent` object into your `Component` array, you'll run directly into the problem of object-slicing: https://stackoverflow.com/questions/274626/what-is-object-slicing – Jeremy Friesner Nov 17 '22 at 03:54

1 Answers1

6

'I have an array of components, and inside could be any child class of "Component", like "TransformComponent".' - this statement is false. If you have an array of Component objects, then at each index in the array, there's exactly a Component-typed object and not a descendant.

If you'd like to store multiple (e.g. Base-Descendants) types, you have two main choices:

  • use container of (smart) pointers: std::vector<std::unique_ptr<Component>> components
  • use variants: std::vector<std::variant<Component, TransformComponent/*, ... other types*/> components>;
lorro
  • 10,687
  • 23
  • 36