Herencia y polimorfismo en C++: clases funcionario, oficial de justicia y bombero
Ejemplo de herencia y polimorfismo en C++
A continuación se presenta un programa en C++ que muestra el uso de herencia, funciones virtuales y gestión dinámica de memoria mediante la clase base funcionario y sus clases derivadas oficialjusticia y bombero.
Código fuente
#include "stdafx.h"
#include "iostream.h"
#include <string.h>
class funcionario{
protected:
char *dni;
double salario;
public:
funcionario(char *pdni = "", double nomina=0);
virtual ~funcionario();
virtual void insertar ();
virtual void mostrar ();
};
funcionario::funcionario(char *pdni, double nomina){
dni = new char [strlen(pdni)+1];
strcpy(dni,pdni);
salario = nomina;
cout << "Constructor funcionario" <<endl;
}
void funcionario::insertar(){
dni = new char[10];
cout << "Introducir Dni Funcionario: \n" << endl;
cin >> dni;
cout << "\n\nIntroducir salario del funcionario: \n";
cin >> salario;
}
void funcionario::mostrar()
{
cout << "\nFuncionario sin especificar profesion con DNI: " << dni << endl;
cout << " y salario " << salario << " euros.\n " << endl;
}
funcionario::~funcionario(){
delete []dni;
cout << "Destructor::funcionario" << endl;
}
class oficialjusticia:public funcionario{
protected:
int horas_mes;
char *juzgado;
public:
oficialjusticia(int horasmes=0,char *pjuzgado="",char *pdni="",double nomina=0);
~oficialjusticia();
void insertar();
void mostrar();
};
oficialjusticia::oficialjusticia(int horasmes,char *pjuzgado,char *pdni,double nomina):funcionario(pdni,nomina){
juzgado = new char[strlen(pjuzgado)+1];
strcpy(juzgado,pjuzgado);
horas_mes = horasmes;
cout << "Constructor oficialjusticia" << endl;
}
void oficialjusticia::insertar(){
dni = new char[10];
juzgado = new char [30];
cout << "Introducir Dni Oficial de Justicia: \n" << endl;
cin >> dni;
cout << "\nIntroducir salario de Oficial de Justicia: \n" << endl;
cin >> salario;
cout << "\nIntroducir numero de horas trabajadas al mes " << endl;
cin >> horas_mes;
cout << "\nIntroducir el nombre de la ciudad del juzgado " << endl;
cin >> juzgado;
}
void oficialjusticia::mostrar(){
cout << "Oficial de Justicia con " << dni << " que trabaja " << horas_mes << " horas al mes " << endl;
cout << " en el juzgado de " << juzgado << " y con un salario de " << salario << endl;
cout << endl;
cout << endl;
}
oficialjusticia::~oficialjusticia(){
delete[] juzgado;
cout << "Destructor::oficialjusticia" << endl;
}
class bombero:public funcionario{
protected:
char *distrito;
int promocion;
public:
bombero(char *pdistrito="",int promo = 0 , char*pdni="",double nomina=0);
~bombero();
void insertar();
void mostrar();
};
bombero::bombero(char *pdistrito,int promo ,char *pdni,double nomina):funcionario(pdni,nomina){
distrito = new char[strlen(pdistrito)+1];
strcpy(distrito,pdistrito);
promocion = promo;
cout << "Constructor bombero" << endl;
}
void bombero::insertar(){
dni = new char[10];
distrito = new char [30];
cout << "Introducir Dni del Bombero \n" << endl;
cin >> dni;
cout << "\nIntroducir salario del Bombero: \n" << endl;
cin >> salario;
cout << "\nIntroducir año de promoción" << endl;
cin >> promocion;
cout << "\nIntroducir distrito asignado " << endl;
cin >> distrito;
}
void bombero::mostrar(){
cout << "Bombero con " << dni << " de la promoción del año " << promocion << endl;
cout << " que trabaja en el distrito " << distrito << " y con un salario de " << salario << endl;
cout << endl;
cout << endl;
}
bombero::~bombero(){
delete[] distrito;
cout << "Destructor::bombero" << endl;
}
void main(int argc, char* argv[])
{
funcionario *fp1 = new funcionario("11258789C",20000);
funcionario *fp2 = new oficialjusticia(160,"Barcelona","70546987Z",19000);
funcionario *fp3 = new bombero("Salamanca",2002,"21546987B",30000);
funcionario *fp4 = new bombero();
funcionario *fp5 = new oficialjusticia();
funcionario *fp6 = new funcionario();
fp1->mostrar();
fp2->mostrar();
fp3->mostrar();
fp4->insertar();
fp4->mostrar();
fp5->insertar();
fp5->mostrar();
fp6->insertar();
fp6->mostrar();
delete fp1;
delete fp2;
delete fp3;
delete fp4;
delete fp5;
delete fp6;
}Descripción del funcionamiento
El programa define una clase base funcionario con los atributos dni y salario. Las clases oficialjusticia y bombero heredan de ella y añaden atributos propios. Gracias a los métodos virtuales, al invocar mostrar() o insertar() a través de un puntero de tipo funcionario, se ejecuta la versión correspondiente a la clase real del objeto (polimorfismo).
Gestión de memoria
Como el programa reserva memoria dinámicamente con new[], es fundamental liberarla con delete[] en los destructores. Por ese motivo el destructor de la clase base se declara como virtual, de modo que al ejecutar delete sobre un puntero base se invoquen también los destructores de las clases derivadas.
Observaciones
- El método
insertar()de cada clase reserva nuevamente memoria para dni (y para juzgado o distrito) sin liberar la anterior, lo que puede provocar fugas de memoria. - En el destructor de bombero el mensaje original indicaba "Destructor::oficialjusticia"; se ha corregido a "Destructor::bombero".
- La lectura con
cin >>de cadenas en buffers de tamaño fijo puede provocar desbordamientos si la entrada es más larga de lo previsto.