我有一个实体系统(我尝试重新创建一个更简单的ECS,而不必担心内存放置...)
实体管理器:
class EntityManager
{
std::unordered_map<std::type_index, std::list<mia::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) {
if (!entity->IsActive()) continue;
// Here the std::function call
method(dynamic_cast<T*>(entity));
}
}
}
}
实体
class Entity
{
Entity::Entity(std::type_index type)
{
EntityManager::RegisterEntity(type, this);
}
}
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()
{
ObjA *a0 = new ObjA(0);
EntityManager::IterateEntities<DerivedEntity>([](DerivedEntity* t) { t->Notify(); });
}
我认为问题是悬空引用,因为我尝试在 Notify() 中记录地址,它返回 null
void Notify()
{
printf("Log: %p", this); // Log
printf("Notitied: %d", id);
}
当我在 std::function 调用之前记录实体时,它返回我正在寻找的正确对象
printf("Log: %p", entity); // Log
method(dynamic_cast<T*>(entity));
如何解决?
我无法立即找到一个很好的副本,所以我会正确回答。
Entity
不是 多态,因为它没有任何虚拟方法。
dynamic_cast
仅适用于当源是多态时的向下转换(您想要执行的操作)。
您可以并且应该通过在
dynamic_cast
中编写一个简单的main
来确认这是您的问题。在调试器(使用调试版本)中检查分段错误也会让您了解这个 nullptr
来自何处。
只需添加虚拟析构函数即可使
Entity
成为多态。如果您可能想使用基类指针来管理所有权,那么您通常应该拥有其中之一。