Historia de la pregunta:
En C++ se introdujo soporte para programación orientada a objetos, fundamental para los lenguajes modernos. Para implementar el polimorfismo se usaron funciones virtuales. Esto permitió llamar a la implementación correcta del método en tiempo de ejecución y no solo en tiempo de compilación, lo cual es crítico para arquitecturas con herencia.
Problema:
Un error común es la confusión entre la llamada estática y dinámica a métodos, destructores virtuales olvidados, trabajo incorrecto con herencia (por ejemplo, slicing de objeto, llamada a la versión base en lugar de la sobreescrita). A menudo se confunde cuándo realmente funciona el polimorfismo.
Solución:
Una función virtual se declara con la palabra clave virtual en la clase base y puede ser sobreescrita en la derivada. Si se llama a la función a través de un puntero o referencia a la clase base, se ejecutará la versión de la clase derivada.
Ejemplo de código:
struct Base { virtual void foo() { std::cout << "Base::foo "; } }; struct Derived : Base { void foo() override { std::cout << "Derived::foo "; } }; void call(Base& b) { b.foo(); } int main() { Derived d; call(d); // Imprimirá Derived::foo }
Características clave:
¿Funciona el polimorfismo al pasar un objeto por valor?
No. Pasar por valor conduce a "slicing" — se copia solo la parte correspondiente al tipo del parámetro (normalmente la clase base), el polimorfismo se desactiva.
Ejemplo de código:
void call(Base b) { b.foo(); } // siempre llama a Base::foo
¿Es necesario declarar el destructor como virtual en la clase base?
Sí, si se prevé la eliminación de objetos derivados a través de un puntero a la clase base. De lo contrario, habrá fugas de memoria o recursos no liberados.
Ejemplo de código:
struct Base { virtual ~Base() {} };
¿Qué sucederá si no se usa la palabra clave override en la clase derivada?
Si no se especifica override en la clase derivada, pero se cambia accidentalmente la firma de la función (por ejemplo, omitiendo const o cometiendo un error en los parámetros), la función no sobreescribirá la virtual, se creará una nueva y el polimorfismo no funcionará como se espera.
El programador no declaró el destructor de la clase base como virtual; eliminar un arreglo de objetos a través de un puntero base llevó a una fuga de memoria.
Pros:
Contras:
Se declaró un destructor virtual; solo se utilizaron referencias/punteros al tipo base. El polimorfismo funcionó correctamente.
Pros:
Contras: