Contenedores y downcasting en C++
En esta receta se explica cómo hacer downcasting de los elementos de un contenedor a una clase más derivada.
Introducción
Supongamos que tenemos la siguiente jerarquía (nos servirá a lo largo de toda la receta):class A {
public:
virtual ~A() {}
};
class B : public A {
public:
string getB() {
return "Soy de tipo B";
}
};
class C : public A {
public:
string getC() {
return "Soy de tipo C";
}
};
El vector de B's y C's
En muchas ocasiones, utilizamos los contenedores de C++ (como vector, stack...) para almacenar distintos tipos de datos. Por ejemplo, imagina que queremos tener un 'vector' que contenga tanto instancias de 'B' como de 'C'. En C++ es necesario crear un vector de la clase padre de ambas, o sea, un 'vector' de A's. Un pensamiento ingenuo (como el mío), implementaría esto mismo así:B b;
C c;
....
vector<A> v;
v.push_back(b);
v.push_back(c);
....
/*
Aquí el downcasting. Pero habrá una sorpresa...
*/
Solución
Antes de dar la solución, vamos a pensar qué queremos realmente. Queremos tener un contenedor que tenga varios tipos de objetos. Hemos visto que el compilador hace slicing de los objetos si estos son instancias. Pero si lo que introducimos en el contenedor son referencias a los objetos, el Object Slicing no ocurre, por lo que tendremos los objetos completos para luego hacer el downcasting. De esta forma, el código correcto sería el siguiente:// El upcasting se hace sin problemas (Polimorfismo)
A* b = new B();
A* c = new C();
....
vector<A*> v;
v.push_back(b);
v.push_back(c);
....
// Downcasting
B* be = dynamic_cast<B*>(v[0]);
C* ce = dynamic_cast<C*>(v[1]);
cout << be->getB() << endl;
cout << ce->getC() << endl;
Referencias
[ show comments ]
blog comments powered by Disqus