No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Polimorfismo

15/16
Recursos

Aportes 8

Preguntas 2

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

Encontré este recurso sobre el casting y un ejemplo muy bueno sobre casting con clases

Cast tradicional de C

El cast tradicional consiste en escribir el tipo entre paréntesis delante la variable que quieres convertir.

int a = 5;
float b = (float) a;

Esta forma de cast puede actuar como muchas de las otras formas de cast. El problema es que no siempre está claro cuál. Por eso es posible que tu programa acaba haciendo otra cosa que el esperabas y, por eso, suele haber la recomendación de ya no utilizarlo. Con las demás formas de cast habrá menos malentendidos entre tú y tu compilador.

Cast entre tipos nativos de C++

static_cast
El mayor uso de static_cast es convertir tipos nativos. Por ejemplo

int a = 5;
unsigned short int b = static_cast(a);
float c = static_cast(a);

Aunque para el programador los dos static_cast parecen lo mismo, el compilador debe hacer dos cosas distintas. A convertir de un tipo entero a otro, le basta jugar con los bits. (Básicamente debe llevar el bit de signo a una nueva posición.) Al convertir entre números enteros y números de coma flotante el compilador debe generar código más complejo, ya que la representación de bits es bastante distinta en tipos flotantes.

static_cast sirve también para convertir clases con el operador de cast como veremos más abajo. Si no sabes con qué cast a probar primero, entonces static_cast es una buena opción.
.
Ejemplo de static_cast con clases y polimorfismo:

// Imagina que ya se declaró la clase Vehiculo y la clase Coche

int main () {
	Vehiculo *v; // Puntero a objeto de tipo vehículo.
	Coche c; // Objeto de tipo coche.

	c.setRuedas(4); // Se establece el estado de c.
	c.setPasajeros(7);
	c.setPMA(1885);

	v = &c; // v apunta a un objeto de tipo coche.

	cout << v->getPMA() << endl; // ERROR en tiempo de compilación.

	cout << ((Coche*)v)->getPMA() << endl; // NO recomendable.

	cout << static_cast<Coche*>(v)->getPMA() << endl; // Estilo C++.
	return 0;
}

Codigo:

#include <iostream>
#include <string>

using namespace std;

class Animal {
protected:
    static int numero_animales;
    string alimento;
public:
    Animal();
    ~Animal();
    static int obtenerNumeroAnimales();
    string obtenerAlimento(){
        return alimento;
    };
    void comer(Animal *a){
        cout<<"Este animal está comiendo " << a->alimento<<"... ñom ñom"<<endl;
    };
};

int Animal::numero_animales = 0;

Animal::Animal()
{
    cout<<"Creando nuevo animal ... "<<endl;
    numero_animales += 1;
}

Animal::~Animal()
{
    cout<<"Borrando animal..."<<endl;
    numero_animales-=1;
}

int Animal::obtenerNumeroAnimales()
{
    return numero_animales;
}

class Herviboro : public Animal {
public:
    Herviboro():Animal(){
        this->alimento = "plantas ";
    }
    void pastar(){
        cout<<"Este animal está pasteando ..."<<endl;
    }
};

class Carnivoro : public Animal {
public:
    Carnivoro():Animal(){
        this->alimento = "plantas ";
    }
    void cazar(){
        cout<<"Este animal está cazando ..."<<endl;
    }
};

class Omnivoro : public Herviboro, public Carnivoro{
public: 
    Omnivoro():Herviboro(),Carnivoro(){}
    void comer(){
        cout<<"Este animal come lo que sea ...."<<endl;
    }
};

int main(){
    Animal *a = new Animal();
    Herviboro *h = new Herviboro();
    Carnivoro *c = new Carnivoro();
    Omnivoro *o = new Omnivoro();

    cout<<"Numero de animeles: "<<Animal::obtenerNumeroAnimales()<<endl;
    
    //a->comer();
    
    h->pastar();
    //h->comer();
    a->comer(h); 

    c->cazar();
   // c->comer();
   a->comer(c);
    cout<<"omnivoro"<<endl;
    o->comer();

    delete a;
    cout<<"Numero de animales"<<Animal::obtenerNumeroAnimales()<<endl;
}

Un uso del polimorfismo es usar un puntero a una clase base para apuntar a objetos derivados en tiempo de ejecución, usando un mismo metodo. De esta manera se va a llamar al metodo correspondiente al objeto derivado que esté en memoria en ese momento. Ejemplo:

Herbivoro *h = new Herbivoro();
Carnivoro *c = new Carnivoro();
Animal *animal;    // puntero a la clase base de Herbivoro y de Carnivoro
...
animal = h;    // puntero a la clase base que apunta a un objeto Herbivoro en este momento
animal->comer();    // come el herbivoro
...
animal = c;    // puntero a la clase base que apunta a un objeto Carniboro en este momento
animal->comer();    // come el carnivoro

con animal->comer() podemos llamar tanto al herbivoro como al carnivoro (mismo nombre/muchas formas = polimorfismo)

Polimorfismo

Otra manera de entender el polimorfismo es fijarnos en lo que el mismo nombre nos enseña poli hace referencia a multiple o cambio y morfismo nos habla de la forma. Si unimos ambas ideas entendemos que el polimosfisma aborda el cambio de forma de los objetos, osea, como un mismo objeto con un comportamiento ya determinado puede cambiar de forma o puede tener multiples formas al momento de compilar o ejecutar nuestro programa.

Tenemos varios tipos de polimorfismo de los cuales podemos destacar dos de los mas utilizados como lo son:

Overload (Sobrecarga)
Override (Sobrescritura)

https://www.geeksforgeeks.org/function-overloading-vs-function-overriding-in-cpp/

Este recurso abunda mas este tema.

Me gustaría un video adicional que explique cuando en una función se pasan parámetros por valor y por referencia. Incluso he visto que utilizan punteros anidados tipo \*\*

Polimorfismo: Es la característica que permite a objetos de diferente clase intercambiar mensajes con una misma estructura.
Se puede implementar de muchas maneras

ADVERTENCIA CON LOS PUNTEROS. Llamarlos después de haberlos liberado genera comportamiento indeterminado.

De hecho hay un corrido tumbado que lo explica