¿Cómo obtener todas las clases derivadas de una clase base en C++?
Estoy implementando un motor de juegos en C++ que utiliza un ECS (Sistema de Entidad-Componente).
Cada GameObject puede tener múltiples Componentes (almacenados en el vector std::vector<component*> _components del GameObject).
Tengo un método que me permite obtener un Componente de un GameObject especificando el tipo de Componente que quiero:
“`c++
// En GameObject.h
template <typename t=""> T* GetComponent() {
for (Component* c : _components) {
if (typeid(*c) == typeid(T)) return (T*)c;
}
return nullptr;
}
<pre><code><br />“`c++
// En main.cpp
RandomComponent* RC = gameObject.GetComponent<randomcomponent>();
Ahora supongamos que tengo los siguientes Componentes definidos:
“`c++
class TerrainComponent { /* … <em>/ }
class PerlinTerrainComponent : public TerrainComponent { /</em> … <em>/ }
class FlatTerrainComponent : public TerrainComponent { /</em> … */ }
// Y posiblemente muchos más
<pre><code><br />Y tengo GameObjects en el mundo, que todos tienen una clase derivada de TerrainComponent adjunta.
Mi problema es que necesitaría una forma de obtener el TerrainComponent de un mundo de la siguiente manera:
“`c++
TerrainComponent* TC = world.GetComponent<terraincomponent>();
Y obtener cualquier tipo de componente derivado de TerrainComponent adjunto al mundo (que en realidad será una clase derivada de TerrainComponent).
¿Es posible, en C++, implementar un método que me permita hacer eso (obtener todas las clases derivadas de una clase), sin tener que actualizar manualmente una lista de clases derivadas de TerrainComponent?</component*>
davy.ai
Sí, es posible en C++ implementar un método que te permita obtener todas las clases derivadas de una clase sin actualizar manualmente una lista de clases derivadas. Una forma de lograr esto es utilizando
std::is_base_of
y metaprogramación de plantillas. Aquí hay un ejemplo de implementación del métodoGetComponent
:“`c++
template
T* GetComponent() {
for (Component* c : _components) {
if (std::is_base_of<terraincomponent, t=””>::value) {
// Si T es una clase base de TerrainComponent, verifica cualquier clase derivada de TerrainComponent
TerrainComponent* tc = dynamic_cast<terraincomponent*>(c);
if (tc && dynamic_cast<t*>(tc)) {
// Si c es una clase derivada de TerrainComponent y es del tipo T, devuélvelo
return dynamic_cast<t*>(c);
}
}
else {
// Si T no es una clase base de TerrainComponent, verifica una coincidencia exacta de tipos
if (typeid(*c) == typeid(T)) return dynamic_cast<t*>(c);
}
}
return nullptr;
}
Ten en cuenta que esta implementación actualmente solo funciona para clases que son directa o indirectamente derivadas de
TerrainComponent
. Si tienes herencia múltiple o herencia virtual, es posible que debas modificar la implementación para tener eso en cuenta.</t></t></t></terraincomponent></terraincomponent,>