Reputation: 10895
I am attempting to create a std::vector<SystemBase>
class member that stores multiple systems that all derive from SystemBase
. However this class has a reference and thus has no sensible default constructor:
class SystemBase {
public:
SystemBase() = delete;
explicit SystemBase(entt::registry &Registry) : Registry{Registry} {}
virtual ~SystemBase() = default;
SystemBase(const SystemBase &) = delete;
SystemBase(SystemBase &&) = delete;
auto operator=(const SystemBase &) -> SystemBase & = delete;
auto operator=(SystemBase &&) -> SystemBase & = delete;
virtual auto update(const sf::Time DeltaTime) const -> void;
protected:
entt::registry &Registry;
};
A system that inherits looks as follows:
class LocalToWorldSystem final : public SystemBase {
public:
explicit LocalToWorldSystem(entt::registry &Registry) : SystemBase{Registry} {};
auto update(const sf::Time DeltaTime) const -> void override;
};
When trying to initialize a vector of systems I get an error:
std::vector<SystemBase> Systems{LocalToWorldSystem{Registry}};
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Error: Call to deleted constructor of 'const SystemBase'.
Why does this happen? My current workaround is to use a std::vector<std::unique_ptr<SystemBase>>
but I'd like to know why this issue pops up in the first place.
Upvotes: 0
Views: 76
Reputation: 275730
In C++, variables and objects of type X are actually objects of type X. They are never objects of a derived type.
Pointers to base can point at derived. Derived objects have a base class subobject in them. But a vector of foo contains actual foos.
In many C++ derived languages, variables of object type are actually pointers (often called references) to said objects. This often leads to primitive types having value semantics, while object types have reference or pointer semantics.
A vector of unique ptrs, meanwhile, can store pointers to base that point to derived.
Upvotes: 1
Reputation: 26166
I'd like to know why this issue pops up in the first place.
If you're coming from Java and similar languages, you need to realize objects in Java are implicitly references or pointers. They have an indirection.
In C++ objects do not have that indirection, they are the objects themselves. And so a SystemBase
only has storage for SystemBase
. It knows nothing about the space needed for derived classes.
Thus you need the std::unique_ptr
to have the same indirection as in Java. This comes with a runtime cost, like in Java.
Upvotes: 1