Bienvenidos sean a este post, hoy veremos una de las etapas de TMP.
En este post hablamos sobre polimorfismo, y podemos resumirlo como multiples funciones bajo el mismo nombre. Siendo que el polimorfismo dinamico nos permite determinar la funcion actual que usaremos al momento de ejecucion. En cambio, el polimorfirmo estatico solo sabra la funcion actual que debe correr al momento de la compilacion. Por lo general, C++ busca la coincidencia del llamado de una funcion con la definicion correcta de la misma al momento de la compilacion mediante el tipo y/o la cantidad de argumentos. Esto es denominado comunmente como union estatica o sobrecarga. Sin embargo, si usamos una funcion virtual el compilador puede hacer union dinamica o anulacion (overriding) en el momento de ejecucion. Analicemos el siguiente ejemplo:
#include <iostream>
class A
{
public:
A() = default;
virtual void algo() {
std::cout << "algo en A" << std::endl;
}
};
class B: public A
{
public:
B() = default;
virtual void algo() {
std::cout << "algo en B" << std::endl;
}
};
int main()
{
A *p = new B();
p->algo();
delete p;
return 0;
}
Primero definimos una clase con un metodo llamado algo. Este es virtual y muestra un mensaje que esta en la clase A. La siguiente clase es heredera de la clase anteriormente descripta. En esta tambien tenemos un metodo virtual llamado igual pero en este mostramos un mensaje que es invocado de la clase B. En el main, primero definimos un puntero de la clase A pero el constructor sera de la clase heredera. Luego llamaremos al metodo desde el puntero. Y finalmente eliminamos al puntero, compilemos y veamos como es la salida:
$ ./estatico
algo en B
$
Como pueden ver da como resultado que a pesar de que el puntero sea de la clase base, se llamo al metodo de la clase heredera. Sin embargo, en los casos en que el comportamiento del polimorfismo es invariante y se puede determinar al momento de compilación, se puede utilizar el Patrón de Plantilla Curiosamente Recurrente (CRTP por sus siglas en ingles) para poder alcanzar el polimorfismo estatico. Mediante la imitacion del polimorfismo estatico y resolver la union en el momento de compilacion. Esto hara que el programa deje de verificar la tabla de busqueda virtual (virtual-lookup-table) en la ejecucion. Tomemos el codigo anterior y modifiquemoslo de la siguiente manera:
#include <iostream>
template <class B> struct A {
void ui() {
static_cast<B*>(this)->algo();
}
};
struct B: A<B> {
void algo() {
std::cout << "B::algo()" << std::endl;
}
};
int main()
{
A<B> b;
b.ui();
return 0;
}
Esto es similar al codigo anterior pero implementando polimorfismo estatico. Primero definimos un template para un struct denominado como A. En este tendremos una funcion que implementa a static_cast para llamar a la funcion algo. Tal como haciamos anteriormente. El operador static_cast puede ser usado para convertir un puntero a una clase base, a un puntero a una clase derivada. Pero esta funcion no es segura porque no realiza ningun chequeo de tipos durante la ejecucion, otra particularidad es que nos permite procesar punteros ambiguos, lo cual puede ser peligroso. Pese a esto, lo usamos para pasar un puntero de la clase generica y usamos a this para poder llamar a la funcion algo. Luego tenemos un struct que sera heredera de la anterior y pasamos al struct como el tipo generico. Dentro de este tenemos la funcion algo y en este mostraremos un mensaje. En el main, primero definimos un objeto del struct A y como tipo generico pasamos al struct B. Para luego llamar a la funcion mediante este objeto, veamos como es la salida:
$ ./estatico
B::algo()
$
Como pueden ver se pudo redireccionar correctamente a la funcion a pesar de no tener acceso directamente. Como pueden deducir porque es otra etapa de TMP y nos permite implementar los beneficios de metaprogramacion.
En resumen, hoy hemos visto polimorfismo estatico, que es, para que sirve, como se aplica, y un ejemplo practico para verlo en accion. Espero les haya resultado de utilidad sigueme en tumblr, Twitter o Facebook para recibir una notificacion cada vez que subo un nuevo post en este blog, nos vemos en el proximo post.


Donatión
It’s for site maintenance, thanks!
$1.50
