Convirtiendo un puntero a puntero a Downcasting
Estoy aprendiendo polimorfismo en C++ y no puedo convertir un puntero a un puntero. Tengo una clase Base y una clase Derived que extiende Base. Y quiero crear un conjunto de objetos Derived usando una función Base **derivedFactory(size_t size)
. Intenté hacer Base** array = new Derived*[size];
pero el compilador dice que no puede convertir de Derived* a Base*. Así que intenté lo siguiente:
“`c++
Base *derivedFactory(size_t size)
{
Base *array = new Derived[size];
for (size_t idx = 0; idx < size; ++idx)
{
Derived derived = Derived();
array[idx] = derived;
}
Base** arrayBase = &array;
return arrayBase;
}
Y compila. Pero luego, cuando quiero acceder a todos los objetos Derived, el main.cc lanza un `Segmentation fault (core dumped)`. Ejecuta `hello(cout)` pero luego lanza antes de terminar la primera iteración del bucle.
¿Podrías ayudarme, por favor?
Main.cc
```c++
#include "main.ih"
int main()
{
Base **bp = derivedFactory(10);
for (size_t idx = 0; idx <= 10; ++idx)
{
bp[idx]->hello(cout);
cout << "No imprime\n";
}
}
</code></pre>
Clase Base:
```c++
class Base
{
private:
virtual void vHello(std::ostream &out)
{
out << "Hola desde Base\n";
}
public:
void hello(std::ostream &out)
{
vHello(out);
}
};
Clase Derived:
```c++
class Derived : public Base
{
std::string d_text;
private:
void vHello(std::ostream &out) override
{
out << d_text << '\n';
}
public:
Derived()
{
d_text = "hola desde Derived";
}
virtual ~Derived()
{}
};
¡Gracias!
davy.ai
El problema en el código está relacionado con la gestión de memoria de los objetos asignados dinámicamente. Al crear el objeto
array
, se crea un puntero a un objetoDerived
, pero el puntero es de tipoBase*
, lo cual es válido ya queDerived
es una subclase deBase
.Sin embargo, cuando el bucle inicializa los objetos
Derived
, crea una copia de un objetoDerived
y lo asigna al punteroBase
. Esto crea un problema de “object slicing” donde los valores y el comportamiento específicos deDerived
se pierden, y solo queda la parteBase
.Además, al usar
Base** arrayBase = &array;
, se crea un puntero a un puntero donde el valor es la dirección dearray
. Dado quearray
es una variable local de la función, cuando sale del ámbito al finalizar la función,arrayBase
se convierte en un puntero colgante y acceder a su valor resultará en un comportamiento indefinido como fallas de segmentación y cierres inesperados.Un enfoque mejor para crear un array de objetos
Derived
que se pueda acceder de forma polimórfica como punterosBase
es utilizar unstd::vector
en lugar de arrays de estilo C. Aquí hay un ejemplo de implementación:“`c++
#include
std::vector<base> derivedFactory(size_t size)
{
std::vector<base> vec;
}
Ten en cuenta que después de acceder a los objetos, debes eliminarlos explícitamente para evitar fugas de memoria, ya que fueron creados de forma dinámica con
new
.Con estos cambios, el código debería funcionar correctamente sin ningún tipo de fallos de segmentación o cierres inesperados.</base></base></base*>