También podemos declarar punteros a una clase
base, y luego asignarle la dirección de un objeto de
una clase derivada. Esta técnica es llamada
polimorfismo.
Polimorfismo es un concepto donde un mismo
nombre puede denotar objetos de clases diferentes
que están relacionadas por una clase base común.
CMotor * pM;
pM = new CElectricMotor;
Este tipo de asignación es llamada “ligado” dinámico
“dynamic binding” porque el tipo exacto asignado al
puntero es desconocido hasta el momento de la
ejecución.
Problema de ligado dinámico
Problema de ligado dinámico
Sin embargo, hay un pequeño problema cuando
usamos ligado dinámico. Si no somos cuidadosos, el
compilador C++ puede llamar las funciones Input and
Display de las clase CMotor:
CMotor * pM; // base pointer type
pM = new CElectricMotor;
La solución al problema de la trasparencia previa es fácil
de solucionar declarando las funciones Input and Display
como virtuales.
El calificativo virtual le dice al compilador que genere
código que mire al tipo del objeto en tiempo de ejecución y
use esta información para seleccionar la versión apropiada
de la función.
class CMotor {
...
virtual void Display() const;
virtual void Input();
...
};
Funciones Virtuales
Funciones Virtuales
Es recomendable definir también como virtuales las
funciones en la clase derivada, en las clases
CGasMotor y CElectricMotor en este caso.
A menudo, un puntero será pasado a una función
que pide un puntero a la clase base. Cuando la
función es llamada, podemos pasar cualquier puntero
como parámetro actual, siempre y cuando este sea
derivado de la clase base.
void GetAndShowMotor( CMotor * pC )
{
pC->Input();
cout << "\nHere's what you entered:\n";
pC->Display();
cout << "\n\n";
}
Funciones Virtuales
Funciones Virtuales
Ejemplo de llamados a GetAndShowMotor con
diferentes tipos de punteros.
CGasMotor * pG = new CGasMotor;
GetAndShowMotor( pG );
CElectricMotor * pE = new CElectricMotor;
GetAndShowMotor( pE );
CMotor * pM = new CGasMotor;
GetAndShowMotor( pM );
// view output...
(Salida de la diapositiva previa)
[GasMotor]: Enter the Motor ID: 234323
Enter the number of cylinders: 3
Here's what you entered:
[GasMotor] ID=234323, Cylinders=3
[ElectricMotor]: Enter the Motor ID: 234324
Voltage: 220
Here's what you entered:
[ElectricMotor] ID=234324, Voltage=220
[GasMotor]: Enter the Motor ID: 44444
Enter the number of cylinders: 5
Here's what you entered:
[GasMotor] ID=44444, Cylinders=5
Creación de un vector de Motores
Creación de un vector de Motores
Un vector de punteros CMotor puede contener
punteros a cualquiera tipo de objeto derivado de
CMotor.
vector<CMotor*> vMotors;
CMotor * pMotor;
pMotor = new CElectricMotor("10000",110);
vMotors.push_back(pMotor);
pMotor = new CGasMotor("20000",4);
vMotors.push_back(pMotor);
pMotor = new CElectricMotor("30000",220);
vMotors.push_back(pMotor);
pMotor = new CGasMotor("40000",2);
vMotors.push_back(pMotor);
Despliegue de Vectores
Despliegue de Vectores
La función que despliega tales vectores no necesita
saber exactamente qué tipo de puntero están en el
vector mientras se llame a funciones virtuales.
Liberación de almacenamiento
Liberación de almacenamiento
Debemos liberar el almacenamiento usado por cada
objeto motor. Este bucle remueve los punteros uno
por uno.
for(int i=0; i < vMotors.size(); i++)
{
delete vMotors[i]; // delete each motor
}
El operador delete acede a información que le
permite saber exactamente cuanto almacenamiento
liberar por cada puntero (aun cuando los motores
ocupan distintos tamaños).
Una función virtual pura no tiene implementación.
Esto es identificado con un "= 0" al final de la
declaración.
Una función virtual pura requiere que la función sea
implementada en la clase derivada.
Comentarios de: Polimorfismo y Funciones Virtuales (0)
No hay comentarios