C++ Polimorfismo con ejemplo

ยฟQuรฉ es el polimorfismo en C++?

In C++, el polimorfismo hace que una funciรณn miembro se comporte de manera diferente segรบn el objeto que la llama/invoca. Polimorfismo es una palabra griega que significa tener muchas formas. Ocurre cuando tienes una jerarquรญa de clases relacionadas mediante herencia.

Por ejemplo, supongamos que tenemos la funciรณn makeSound(). Cuando un gato llama a esta funciรณn, producirรก un maullido. Cuando una vaca invoca la misma funciรณn, emitirรก el sonido de un maullido.

 Polimorfismo en C++

Aunque tenemos una funciรณn, se comporta de manera diferente en diferentes circunstancias. La funciรณn tiene muchas formas; por tanto, hemos logrado el polimorfismo.

Tipos de polimorfismo

C++ admite dos tipos de polimorfismo:

  • Polimorfismo en tiempo de compilaciรณn y
  • Polimorfismo en tiempo de ejecuciรณn.

Tipos de polimorfismo

Compilar polimorfismo de tiempo

Se invocan las funciones sobrecargadas haciendo coincidir el nรบmero y el tipo de argumentos. La informaciรณn estรก presente durante el tiempo de compilaciรณn. Esto significa que C++ El compilador seleccionarรก la funciรณn correcta en el momento de la compilaciรณn.

El polimorfismo en tiempo de compilaciรณn se logra mediante la sobrecarga de funciones y la sobrecarga de operadores.

Sobrecarga de funciones

La sobrecarga de funciones ocurre cuando tenemos muchas funciones con nombres similares pero argumentos diferentes. Los argumentos pueden diferir en tรฉrminos de nรบmero o tipo.

Ejemplo

#include <iostream> 
using namespace std;

void test(int i) {
	cout << " The int is " << i << endl;
}
void test(double  f) {
	cout << " The float is " << f << endl;
}
void test(char const *ch) {
	cout << " The char* is " << ch << endl;
}

int main() {
	test(5);
	test(5.5);
	test("five");
	return 0;
}

Salida:

Sobrecarga de funciones

Aquรญ hay una captura de pantalla del cรณdigo:

Sobrecarga de funciones

Code Explicaciรณn:

  1. Incluya el archivo de encabezado iostream en nuestro cรณdigo. Podremos utilizar sus funciones.
  2. Incluya el espacio de nombres estรกndar en nuestro cรณdigo. Podremos utilizar sus clases sin llamarlo.
  3. Cree una funciรณn llamada prueba que tome un parรกmetro entero i. El { marca el comienzo del cuerpo de la prueba de funciรณn.
  4. Declaraciรณn que se ejecutarรก si se invoca/llama la funciรณn de prueba anterior.
  5. Fin del cuerpo de la prueba de funciรณn anterior.
  6. Cree una funciรณn llamada prueba que tome un parรกmetro flotante f. El { marca el comienzo del cuerpo de la prueba de funciรณn.
  7. Declaraciรณn que se ejecutarรก si se invoca/llama la funciรณn de prueba anterior.
  8. Fin del cuerpo de la prueba de funciรณn anterior.
  9. Cree una funciรณn llamada prueba que tome un parรกmetro de carรกcter ch. El { marca el comienzo del cuerpo de la prueba de funciรณn.
  10. Declaraciรณn que se ejecutarรก si se invoca/llama la funciรณn de prueba anterior.
  11. Fin del cuerpo de la prueba de funciรณn anterior.
  12. Llame a la funciรณn principal(). El { marca el comienzo del cuerpo de la funciรณn.
  13. Llame a la funciรณn test y pรกsele 5 como valor del argumento. Esto invoca la funciรณn de prueba que acepta un argumento entero, es decir, la primera funciรณn de prueba.
  14. Llame a la funciรณn test y pรกsele 5.5 como valor del argumento. Esto invocarรก la funciรณn de prueba que acepta un argumento flotante, es decir, la segunda funciรณn de prueba.
  15. Llame a la funciรณn test y pรกsele cinco como valor del argumento. Esto invocarรก la funciรณn de prueba que acepta un argumento de carรกcter, es decir, la tercera funciรณn de prueba.
  16. El programa debe devolver un valor si se ejecuta correctamente.
  17. El final del cuerpo de la funciรณn main().

Tenemos tres funciones con el mismo nombre pero diferentes tipos de argumentos. Hemos logrado el polimorfismo.

OperaSobrecarga de Tor

In Operator Overloading, definimos un nuevo significado para un C++ Operador. Tambiรฉn cambia el funcionamiento del operador. Por ejemplo, podemos definir el operador + para concatenar dos cadenas. Lo conocemos como el operador de suma para sumar valores numรฉricos. Segรบn nuestra definiciรณn, cuando se coloca entre nรบmeros enteros, los sumarรก. Cuando se coloca entre cadenas, las concatenarรก.

Ejemplo

#include<iostream> 
using namespace std;

class ComplexNum {
private:
	int real, over;
public:
	ComplexNum(int rl = 0, int ov = 0) {
		real = rl;   
		over = ov; 
	}

	ComplexNum operator + (ComplexNum const &obj) {
		ComplexNum result;
		result.real = real + obj.real;
		result.over = over + obj.over;
		return result;
	}
	void print() { 
		cout << real << " + i" << over << endl; 
	}
};
int main()
{
	ComplexNum c1(10, 2), c2(3, 7);
	ComplexNum c3 = c1+c2;
	c3.print();
}

Salida:

OperaSobrecarga de Tor

Aquรญ hay una captura de pantalla del cรณdigo:

OperaSobrecarga de Tor

OperaSobrecarga de Tor

Code Explicaciรณn:

  1. Incluya el archivo de encabezado iostream en nuestro programa para poder utilizar sus funciones.
  2. Incluya el espacio de nombres estรกndar en nuestro programa para poder usar sus clases sin llamarlo.
  3. Crea una clase llamada ComplexNum. El { marca el comienzo del cuerpo de la clase.
  4. Utilice el modificador de acceso privado para marcar las variables como privadas, lo que significa que solo se puede acceder a ellas desde dentro de la clase.
  5. Defina dos variables enteras, reales y superiores.
  6. Utilice el modificador de acceso pรบblico para marcar el constructor como pรบblico, lo que significa que serรก accesible incluso desde fuera del clase.
  7. Crea el constructor de la clase e inicializa las variables.
  8. Inicializa el valor de la variable real.
  9. Inicialice el valor de la variable over.
  10. Fin del cuerpo del constructor.
  11. Necesitamos anular el significado del operador +.
  12. Crea el tipo de datos resultado del tipo ComplexNum.
  13. Utilice el operador + con nรบmeros complejos. Esta lรญnea sumarรก la parte real de un nรบmero con la parte real de otro nรบmero.
  14. Utilice el operador + con nรบmeros complejos. Esta lรญnea sumarรก la parte imaginaria de un nรบmero a la parte imaginaria de otro nรบmero.
  15. El programa devolverรก el valor de la variable resultado tras una ejecuciรณn exitosa.
  16. Fin de la definiciรณn del nuevo significado del operador +, es decir, la sobrecarga.
  17. Llame al mรฉtodo print().
  18. Imprima el nuevo nรบmero complejo despuรฉs de la suma en la consola.
  19. Fin del cuerpo de la funciรณn print().
  20. Fin del cuerpo de la clase ComplexNum.
  21. Llame a la funciรณn principal().
  22. Pasar los valores de las partes reales y complejas que se van a sumar. La primera parte de c1 se sumarรก a la primera parte de c2, es decir, 10+3. La segunda parte de c1 se sumarรก a la segunda parte de c, es decir, 2+7.
  23. Realizar una operaciรณn utilizando el operador + sobrecargado y almacenar el resultado en la variable c3.
  24. Imprime el valor de la variable c3 en la consola.
  25. Fin del cuerpo de la funciรณn main().

Polimorfismo en tiempo de ejecuciรณn

Esto sucede cuando el mรฉtodo de un objeto se invoca/llama durante el tiempo de ejecuciรณn en lugar de durante el tiempo de compilaciรณn. El polimorfismo en tiempo de ejecuciรณn se logra mediante la anulaciรณn de funciones. La funciรณn a llamar/invocar se establece durante el tiempo de ejecuciรณn.

Anulaciรณn de funciones

La anulaciรณn de funciones ocurre cuando a una funciรณn de la clase base se le da una nueva definiciรณn en una clase derivada. En ese momento, podemos decir que la funciรณn base ha sido anulada.

Por ejemplo:

#include <iostream>
using namespace std;
class Mammal {

public:
	void eat() {

		cout << "Mammals eat...";
	}

};

class Cow: public Mammal {

public:
	void eat() {

		cout << "Cows eat grass...";
	}
};
int main(void) {

	Cow c = Cow();

	c.eat();

	return 0;

}

Salida:

Anulaciรณn de funciones

Aquรญ hay una captura de pantalla del cรณdigo:

Anulaciรณn de funciones

Code Explicaciรณn:

  1. Importe el archivo de encabezado iostream a nuestro programa para usar sus funciones.
  2. Incluya el espacio de nombres estรกndar en nuestro programa para poder usar sus clases sin llamarlo.
  3. Crea una clase llamada Mamรญfero. El { marca el comienzo del cuerpo de la clase.
  4. Utilice el modificador de acceso pรบblico para configurar la funciรณn que estamos a punto de crear como de acceso pรบblico. Serรก accesible desde fuera de esta clase.
  5. Crea una funciรณn pรบblica llamada comer. El { marca el comienzo del cuerpo de la funciรณn.
  6. Imprime la declaraciรณn agregada a la funciรณn cout cuando se invoca la funciรณn eat().
  7. El final del cuerpo de la funciรณn eat().
  8. Fin del cuerpo de la clase Mamรญfero.
  9. Cree una clase llamada Vaca que herede la clase Mamรญfero. Vaca es la clase derivada, mientras que Mamรญfero es la clase base. El { marca el comienzo de esta clase.
  10. Utilice el modificador de acceso pรบblico para marcar la funciรณn que estamos a punto de crear como de acceso pรบblico. Serรก accesible desde fuera de esta clase.
  11. Anule la funciรณn eat() que se definiรณ en la clase base. El { marca el comienzo del cuerpo de la funciรณn.
  12. La declaraciรณn que se imprimirรก en la consola cuando se invoque esta funciรณn.
  13. Fin del cuerpo de la funciรณn comer().
  14. Fin del cuerpo de la clase Vaca.
  15. Llame a la funciรณn principal(). El { marca el comienzo del cuerpo de esta funciรณn.
  16. Cree una instancia de la clase Cow y asรญgnele el nombre c.
  17. Llame a la funciรณn eat() definida en la clase Cow.
  18. El programa debe devolver un valor al finalizar con รฉxito.
  19. Fin de la funciรณn main().

C++ Funciรณn virtual

Una funciรณn virtual es otra forma de implementar polimorfismo en tiempo de ejecuciรณn en C++. Es una funciรณn especial definida en una clase base y redefinida en la clase derivada. Para declarar una funciรณn virtual, debe utilizar la palabra clave virtual. La palabra clave debe preceder a la declaraciรณn de la funciรณn en la clase base.

Si se hereda una clase de funciรณn virtual, la clase virtual redefine la funciรณn virtual para satisfacer sus necesidades. Por ejemplo:

#include <iostream>  
using namespace std;
class ClassA {
		public:
		virtual void show() {
			cout << "The show() function in base class invoked..." << endl;
		}
	};
	class ClassB :public ClassA {
	public:
		void show() 	{
			cout << "The show() function in derived class invoked...";
		}
	};
	int main() {
		ClassA* a;   
		ClassB b;
		a = &b;
		a->show();      
	}

Salida:

C++ Funciรณn virtual

Aquรญ hay una captura de pantalla del cรณdigo:

C++ Funciรณn virtual

Code Explicaciรณn:

  1. Incluya el archivo de encabezado iostream en el cรณdigo para usar sus funciones.
  2. Incluya el espacio de nombres estรกndar en nuestro cรณdigo para usar sus clases sin llamarlo.
  3. Crea una clase llamada ClassA.
  4. Utilice el modificador de acceso pรบblico para marcar a un miembro de la clase como de acceso pรบblico.
  5. Cree una funciรณn virtual llamada show(). Serรก una funciรณn pรบblica.
  6. El texto que se imprimirรก cuando se invoque show(). El final es un C++ palabra clave, que significa lรญnea final. Mueve el cursor del mouse a la siguiente lรญnea.
  7. Fin del cuerpo de la funciรณn virtual show().
  8. Fin del cuerpo de la clase ClassA.
  9. Creando una nueva clase llamada ClassB que hereda la clase ClassA. ClassA se convierte en la clase base mientras que ClassB se convierte en la clase derivada.
  10. Utilice el modificador de acceso pรบblico para marcar a un miembro de la clase como de acceso pรบblico.
  11. Redefina la funciรณn virtual show() derivada en la clase base.
  12. El texto que se imprimirรก en la consola cuando se invoque la funciรณn show() definida en la clase derivada.
  13. Fin del cuerpo de la funciรณn show().
  14. Fin del cuerpo de la clase derivada, ClassB.
  15. Llame a la funciรณn principal(). La lรณgica del programa debe agregarse dentro de su cuerpo.
  16. Cree una variable de puntero denominada a. Apunta a la clase denominada ClassA.
  17. Cree una instancia de la clase denominada ClassB. La instancia recibe el nombre b.
  18. Asigne los valores almacenados en la direcciรณn b en la variable a.
  19. Invoca la funciรณn show() definida en la clase derivada. Se ha implementado la vinculaciรณn tardรญa.
  20. Fin del cuerpo de la funciรณn main().

Polimorfismo en tiempo de compilaciรณn vs. Polimorfismo en tiempo de ejecuciรณn

Estas son las principales diferencias entre los dos:

Polimorfismo en tiempo de compilaciรณn Polimorfismo en tiempo de ejecuciรณn
Tambiรฉn se llama uniรณn temprana o polimorfismo estรกtico. Tambiรฉn se llama uniรณn tardรญa/dinรกmica o polimorfismo dinรกmico.
El mรฉtodo se llama/invoca durante el tiempo de compilaciรณn. El mรฉtodo se llama/invoca durante el tiempo de ejecuciรณn.
Implementado mediante sobrecarga de funciones y sobrecarga de operadores. Implementado mediante anulaciรณn de mรฉtodos y funciones virtuales.
Ejemplo, sobrecarga de mรฉtodos. Muchos mรฉtodos pueden tener nombres similares pero diferentes nรบmeros o tipos de argumentos. Ejemplo, anulaciรณn de mรฉtodo. Muchos mรฉtodos pueden tener un nombre similar y el mismo prototipo.
Ejecuciรณn mรกs rรกpida ya que el descubrimiento de mรฉtodos se realiza durante el tiempo de compilaciรณn. Ejecuciรณn mรกs lenta ya que el descubrimiento de mรฉtodos se realiza durante el tiempo de ejecuciรณn.
Less Se proporciona flexibilidad para la resoluciรณn de problemas ya que todo se sabe durante el tiempo de compilaciรณn. Se proporciona mucha flexibilidad para resolver problemas complejos ya que los mรฉtodos se descubren durante el tiempo de ejecuciรณn.

Resumen

  • Polimorfismo significa tener muchas formas.
  • Ocurre cuando existe una jerarquรญa de clases relacionadas mediante herencia.
  • Con el polimorfismo, una funciรณn puede comportarse de manera diferente segรบn el objeto que la invoca/llama.
  • En el polimorfismo en tiempo de compilaciรณn, la funciรณn que se invocarรก se establece durante el tiempo de compilaciรณn.
  • En el polimorfismo en tiempo de ejecuciรณn, la funciรณn que se invocarรก se establece durante el tiempo de ejecuciรณn.
  • El polimorfismo en tiempo de compilaciรณn se determina mediante la sobrecarga de funciones y la sobrecarga de operadores.
  • En la sobrecarga de funciones, hay muchas funciones con nombres similares pero argumentos diferentes.
  • Los parรกmetros pueden diferir en nรบmero o tipo.
  • En la sobrecarga del operador, se define un nuevo significado para C++ operadores.
  • El polimorfismo en tiempo de ejecuciรณn se logra mediante la anulaciรณn de funciones.
  • En la anulaciรณn de funciones, una clase derivada proporciona una nueva definiciรณn a una funciรณn definida en la clase base.

Resumir este post con: