¿Cómo borrar una clase derivada de una declaración de puntero de clasebase con CRTP?
Supongamos que tengo un ejemplo de libro de CRTP (patrón de plantilla de recurrencia curiosa) y quiero crear un contenedor de Base* sin especificar la información derivada para recorrer y llamar a interfaces de forma polimórfica.
template<typename T>
class Base
{
public:
void f()
{
static_cast<T*>(this)->f();
}
};
class Derived1 : public Base<Derived1> {
public:
void f()
{
std::cout << "Derived1::f()\n";
}
};
class Derived2 : public Base<Derived2> {
public:
void f()
{
std::cout << "Derived2::f()\n";
}
};
template<typename T>
void apply(Base<T>* ptr) {
ptr->f();
}
int main() {
Base<Derived1>* ptr1 = new Derived1;
Base<Derived2>* ptr2 = new Derived2;
ptr1->f();
ptr2->f();
}
Ahora supongamos que quiero crear un std::vector
(o cualquier otro contenedor, no relevante para la pregunta) de Base* y recorrer llamando a f, pero el compilador no lo permite ya que necesito especificar el argumento de plantilla de Base, lo que prácticamente hace que tenga un vector
de Base<Derived1>*
o Base<Derived2>*
.
¿Existe alguna forma o truco para deshacerse de este argumento de plantilla y crear una colección de Base* con diferentes tipos dinámicos?
Gracias de antemano.
davy.ai
Una solución consiste en utilizar una clase base común para todas las clases derivadas, y hacer que la función
apply
tome un puntero a esa clase base en lugar de la claseBase<t>
. Por ejemplo:Aquí, introducimos una nueva clase
CommonBase
que tiene una función virtualf()
. Esto nos permite crear un vector deCommonBase*
que puede contener punteros a cualquier clase que herede deCommonBase
. Modificamos la claseBase
para que herede deCommonBase
, y hacemos que la funciónapply
tome un puntero aCommonBase
en lugar deBase<t>
. Ahora podemos recorrer el vector deCommonBase*
y llamar a la funciónf()
en cada elemento, lo que llamará a la función sobrescrita adecuada en la clase derivada.</commonbase></t>