Funciones virtuales en C++
En la programación orientada a objetos nos encontramos con el concepto de polimorfismo. No es otra cosa que la capacidad para que diferentes clases derivadas de una misma superclase, utilicen una misma función de forma diferente.
El polimorfismo en C++ se implementa con la ayuda de la funciones virtuales.
Nada mejor que ilustrarlo con un ejemplo.
Tenemos dos clases:
1 2 3 4 5 6 7 8 9 10 11 | class Animal { public: void eat() { std::cout << "Estoy comiendo comida genérica"; } } class Cat : public Animal { public: void eat() { std::cout << "Estoy comiendo comida de gato"; } } |
En la función main tenemos:
1 2 3 4 5 | Animal *animal = new Animal; Cat *cat = new Cat; animal->eat(); // Imprime: "Estoy comiendo comida genérica" cat->eat(); // Imprime: "Estoy comiendo comida de gato" |
Perfecto, en este caso no necesitamos funciones virtuales y todo funciona como esperamos.
Pero si por cualquier motivo necesitamos llamar a la función eat() desde una función intermedia:
1 2 | // Podemos poner esta función al principio de nuestro archivo main.cpp void oneFunction(Animal *animal) { animal->eat(); } |
Modificamos nuestra función main:
1 2 3 4 5 | Animal *animal = new Animal; Cat *cat = new Cat; oneFunction(animal) // Imprime: "Estoy comiendo comida genérica" oneFunction(cat) // Imprime: "Estoy comiendo comida genérica" |
Como podemos comprobar, en este caso siempre se llama a la función eat() de la superclase y no a la de la clase hija (Cat).
La solución es convertir la función eat() en una función virtual:
1 2 3 4 5 | class Animal { public: virtual void eat() { std::cout << "Estoy comiendo comida genérica"; } } |
En el main:
1 2 | oneFunction(animal) // Imprime: "Estoy comiendo comida genérica" oneFunction(cat) // Imprime: "Estoy comiendo comida de gato" |
Aunque no es necesario, a mi me gusta indicar que una función es virtual también en la clase hija. Así, si nos encontramos con una clase de otro programador que hereda de una superclase, sabremos de un solo vistazo cuales son las funciones sobreescritas (override).
Por tanto, nuestra clase Cat quedaría así:
1 2 3 4 5 | class Cat : public Animal { public: virtual void eat() { std::cout << "Estoy comiendo comida de gato"; } } |
Buen artículo!