Reputation: 1
I have a Entity system (I tried to recreated a simpler ECS without much worry on memory placement...)
EntityManager:
class EntityManager
{
static std::unordered_map<std::type_index, std::list<Entity*>> entitiesMap;
public:
static void RegisterEntity(std::type_index type, Entity* entity)
{
if (entitiesMap.find(type) == entitiesMap.end()) {
entitiesMap.insert(std::pair<std::type_index, std::list<Entity*>>(
type,
std::list<Entity*>()
));
}
entitiesMap[type].push_back(entity);
}
template <class T>
static void IterateEntities(std::function<void(T*)> method)
{
static_assert(std::is_base_of<Entity, T>::value, "T must be derived from Entity");
std::type_index type = std::type_index(typeid(T));
auto targetIterator = entitiesMap.find(type);
if (targetIterator != entitiesMap.end()) {
for (Entity* entity : targetIterator->second) {
method(dynamic_cast<T*>(entity));
}
}
}
};
std::unordered_map<std::type_index, std::list<Entity*>> EntityManager::entitiesMap;
Entity
class Entity
{
public:
Entity(std::type_index type)
{
EntityManager::RegisterEntity(type, this);
}
virtual ~Entity() = default;
};
main.cpp
class DerivedEntity : Entity
{
public:
DerivedEntity(int s) : Entity(typeid(DerivedEntity))
{
id = s;
}
int id;
void Notify()
{
printf("Notitied: %d", id); // <--- Segmentation fault
}
};
int main()
{
DerivedEntity *test = new DerivedEntity(0);
EntityManager::IterateEntities<DerivedEntity>([](DerivedEntity* t) { t->Notify(); });
}
I think the problem was dangling reference since I tried to log the address inside Notify() it returns null
void Notify()
{
printf("Log: %p", this); // Log
printf("Notitied: %d", id);
}
while I log the entity before the std::function call, it returns the right object I looking for
printf("Log: %p", entity); // Log
method(dynamic_cast<T*>(entity));
How to fix it?
Upvotes: 0
Views: 63
Reputation: 67802
I can't immediately find a great duplicate for this, so I'll answer properly.
Entity
is not polymorphic, because it doesn't have any virtual methods.
You can see from the documentation that dynamic_cast
only works for down-casting (what you're trying to do) when the source is polymorphic.
You can and should confirm that this is your issue by writing a simple dynamic_cast
right in main
. Examining your segmentation fault in a debugger (with a debug build) would also have given you some idea where this nullptr
was coming from.
You can make Entity
polymorphic by simply adding a virtual destructor. You should usually have one of these anyway if you might want to manage ownership using base-class pointers.
Upvotes: 2