Está en la página 1de 33

Lenguaje C++:

Relaciones entre
clases

Lima, 2018
Abraham Sopla Maslucán
El trabajo que presentamos a continuación, tiene un propósito totalmente académico, es una
lista de ejemplos prácticos de codificación de cada de las relaciones entre clases en lenguaje C++,
entre ellos: relación de dependencia/uso, relación de asociación, relación de agregación, relación
de composición, relación de generalización/ herencia y relación de especialización. En todos ellos
se aplican los principios de la programación orientada a objetos.

Algunos de los ejemplos han sido recopilados, revisados y modificados, con especial cuidado, de
tal manera que cumplan con las reglas tratando de cubrir todos los tipos de relaciones entre
clases. Las imágenes y diagramas han sido elaborados en LuciChart.
Relaciones entre clases en C++
Abraham Sopla Maslucán

Contenido
1. Protected, private y public .......................................................................................................... 4
2. Dependencia/Uso: área de círculo ............................................................................................. 4
3. Dependencia/Uso: Clase1 usa objetos de la clase2 y viceversa .............................................. 5
4. Asociación: una laptop usa parlantes......................................................................................... 5
5. Composición: una laptop tiene microprocesador ..................................................................... 8
6. Agregación: agreguemos contactos a una agenda ................................................................. 10
7. Herencia simple: un estudiante hereda las características de una persona ......................... 14
8. Herencia simple: un automóvil es un vehículo, un camión también ..................................... 15
9. Herencia simple: un médico y un obrero son asalariados, un asalariado es una persona .. 18
10. Especialización: el hijo tiene dos apellidos, el primero del padre y el segundo de la madre
20
11. Cíclica: un empleado puede ser jefe de otro empleado .................................................... 21
12. Problema del diamante ........................................................................................................ 24
13. Caso 1: Un atributo public .................................................................................................... 25
14. Caso 2: un atributo protected .............................................................................................. 25
15. Caso 3: un atributo private ................................................................................................... 26
16. Caso 4: Probando herencia pública, protegida y privada .................................................. 26
17. Caso: superclase con nivel de acceso private ..................................................................... 27
18. Caso: superclase con nivel de acceso protected ................................................................ 28
19. Caso 5: un almacén tiene cuenta y puede estar asociado a cliente ................................. 29
Referencias .......................................................................................................................................... 33

3|Página
Relaciones entre clases en C++
Abraham Sopla Maslucán

Nivel de acceso a atributos y métodos


1. Protected, private y public
Estos tres niveles de acceso a métodos y clases se entienden mejor al momento de resolver
problemas usando relaciones entre clases de herencia.

Protected: se puede acceder a un atributo o método de una clase A directamente desde esta
clase A y desde sus subclases B, C, D, etc.

Private: solamente se puede acceder a un atributo o método de la clase A directamente desde la


misma clase A. En el caso de atributos, para acceder desde otras clases externas B, C, D, etc.,
incluido subclases X, Y, Z, etc., o desde el archivo que contiene el método principal main se
requiere el uso de seters y geters públicos con niveles de acceso público.

Public: se puede acceder a los atributos o métodos de una clase A directamente desde la misma
clase A, subclase B, C, D, etc., además desde otras clases externas, incluido el archivo que tiene
la clase main, mediante el objeto respectivo A.

Relación entre clases:


Dependencia/Uso
2. Dependencia/Uso: área de círculo
Ejemplo1: En una clase que permite resolver problemas geométricos es posible que se requiera
el uso de algunos métodos de una clase externa círculo.

Circulo.h
#include<iostream>
class Circulo {
private:
const double pi = 3.1416;
double radio;
public:
Circulo(){}
Circulo(double _radio) {
radio = _radio;
}
double hallaDiametro()
{
return 2 * radio;
}
double hallaArea()
{
return pi*pow(radio,2);
}
double hallaLongitudCircunferencia()
{
return 2 * pi*radio;

4|Página
Relaciones entre clases en C++
Abraham Sopla Maslucán

}
};
Principal
#include<iostream>
#include<string>
#include"Circulo.h"
using namespace std;

void main()
{
double radio;
cout << "Calculo del area del cuadrado " << endl;
cout << "Valor del radio: ";
cin >> radio;
//Dependencia de uso
Circulo *circulo = new Circulo(radio);
//Cálculos
cout<<"Diametro: "<<circulo->hallaDiametro()<<endl;
cout<<"Longitud de la circunferencia: "<<circulo-
>hallaLongitudCircunferencia()<<endl;
cout<<"Area del circulo: "<<circulo->hallaArea()<<endl;
system("pause");
}

3. Dependencia/Uso: Clase1 usa objetos de la clase2 y viceversa


Clase1.h
#include "Clase2.h"

class Clase1 {
public:
void metodo(Clase2* objeto2) {
}
};
Clase2.h
#include "Clase1.h"

class Clase2 {
public:
void metodo(Clase1* objeto1) {
}
};

Relación entre clases: asociación


4. Asociación: una laptop usa parlantes
Parlante.h
#include<iostream>
#include<string>
using namespace std;
class Parlante {

5|Página
Relaciones entre clases en C++
Abraham Sopla Maslucán

private:
string energia;
public:
Parlante() {}
~Parlante() {}
void setEnergia(string _energia) { energia = _energia; }
string getEnergia() { return energia; }

//Comportamientos
void muestraDatos()
{
cout << "Energía que soporta en Watts: " << energia << endl;
}
};

Laptop.h
#include<iostream>
#include<string>
#include"Parlante.h"
using namespace std;
class Laptop {
private:
string marca="HP";
Parlante *parlante;
public:
//Crear objeto Laptop sin asignarle un objeto de parlante
Laptop() {
}
//Crear objeto Laptop asignándole un objeto de parlante
//Para ello el objeto parlante debe prepararse
Laptop(Parlante *_parlante)
{
parlante = _parlante; //asignamos la dirección del objeto parlante
}
~Laptop() {
}
//Seters y getetrs
//Crear objeto Laptop asignándole un objeto de parlante mediante set
void setParlante(Parlante *_parlante)
{
parlante = _parlante;
}
Parlante* getParlante()
{
return parlante;
}
//Comportamientos
void muestraDatos()
{
cout << "Marca de la Laptop: " << marca << " Energía del parlante: "
<< parlante->getEnergia() << endl;
}
};

Prueba.cpp
#include<iostream>

6|Página
Relaciones entre clases en C++
Abraham Sopla Maslucán

#include<string>
#include "Laptop.h"
using namespace std;
void main()
{
Laptop *laptop = new Laptop();
Parlante *parlante = new Parlante();

//ponemos el dato de energía al parlante


parlante->setEnergia("1400 watts");

//asociamos un parlante a la laptop


laptop->setParlante(parlante);

//imprimir datos de la laptop


laptop->muestraDatos();

//Eliminé el objeto laptop


delete laptop;
laptop = NULL;

//Sin embargo el objeto parlante sigue vivo


cout << "El objeto parlante no ha muerto" << endl;
cout << parlante->getEnergia() << endl;
system("pause");
}

Relación entre clases: composición


En la composición no se puede asignar valores a los atributos en el constructor, romperíamos la
regla de la composición. Los datos se deben agregar a través de su objeto contenedor mediante
los seters y geters del propio objeto incluido.

Microprocesador.h
#include<iostream>
using namespace std;
class Microprocesador
{
private:
int velocidad;
public:
Microprocesador()
{
}

~Microprocesador()
{
}
};
Laptop.h
//Composicion: Una laptop tiene un mricroprocesador
#include<iostream>
#include"Microprocesador.h"
using namespace std;
class Laptop {
private:

7|Página
Relaciones entre clases en C++
Abraham Sopla Maslucán

string marca="Toshiba";
Microprocesador *micro;
public:
Laptop() {
micro = new Microprocesador();
micro = NULL;
//Lo que sea que el constructor haga
}
~Laptop() {
//Lo que sea que el destructor haga
delete micro;
}
}

5. Composición: una laptop tiene microprocesador


Microprocesador.h
#include<iostream>
#include<string>
using namespace std;
//Un objeto cualquiera
class Microprocesador {
private:
string velocidad;
public:
Microprocesador() {}
void setVelocidad(string _velocidad) { velocidad = _velocidad; }
string getVelocidad() { return velocidad; }

//Comportamientos
void muestraDatos()
{
cout << "Velocidad del microprocesador: " << velocidad << endl;
}
};
Laptop.h
//Una laptop TIENE microprocesador
#include<iostream>
#include<string>
#include"Microprocesador.h"
using namespace std;
class Laptop {
string marca="HP";
Microprocesador *microprocesador;
public:
Laptop() {
microprocesador = new Microprocesador();
}
~Laptop() {
delete microprocesador;
microprocesador = NULL;
}
//Metodo importante para acceder a un objeto microprocesador
//Por principio de comprosicion
//No se puede acceder a un objeto microprocesador si no es mediante el objeto
Laptop

8|Página
Relaciones entre clases en C++
Abraham Sopla Maslucán

Microprocesador *getMicroprocesador()
{
return microprocesador;
}
//Comportamientos
void muestraDatos()
{
cout << "Marca de la Laptop: " << marca << " Velocidad del
microprocesador: " << microprocesador->getVelocidad() << endl;
}
};
Prueba.cpp
#include<iostream>
#include<string>
#include "Laptop.h"
using namespace std;
void main()
{
Laptop *laptop = new Laptop();
//Obteniendo la dirección del objeto microprocesador con laptop-
>getMicroprocesador()

//Agregarle un valor al atributo velocidad


laptop->getMicroprocesador()->setVelocidad("2.5 GHz");

//Imprimir datos del microprocesador


cout<<"Velocidad del microprocesador: "<<laptop->getMicroprocesador()-
>getVelocidad() << endl;

//Podríamos ver los datos del microprocesador también siempre y cuando


también veamos los de la laptop
laptop->muestraDatos();

//Destruir laptop
delete laptop;
laptop = NULL;

//Al destruirse laptop también se destruyó microprocesador


system("pause");
}

Relación entre clases: agregación


Una agregación se da en una relación de uno a muchos. En una relación de uno a uno, una
agregación es una asociación.

Tarjeta.h
#include<string>
#include<iostream>
using namespace std;
class Tarjeta
{
private:
string banco;
long numero;

9|Página
Relaciones entre clases en C++
Abraham Sopla Maslucán

public:
Tarjeta()
{
}

~Tarjeta()
{
}
};

Cliente.h
//El cliente usa tarjeta de crédito
#include<string>
#include"Tarjeta.h"
using namespace std;
public class Cliente {
private:
int dni;
string nombre;
Tarjeta *otarjeta;
public:
Cliente() {
//Lo que sea que el constructor haga
}
~Cliente() {
//Lo que sea que el destructor haga
}
//Aquí se da la agregación, en realidad se da en una relación de 1 a
muchos
//Una agregación de uno a uno es una asociación
void setTarjeta(Tarjeta *tarjeta) {
otarjeta=new Tarjeta();
otarjeta = tarjeta;
}
// Más código aquí
}

6. Agregación: agreguemos contactos a una agenda


Contacto.h
//Ejemplo de agregación
//Solución del ejercicio 2 de la práctica de la semana 5
//Recordando que cualquier objeto ya sea compuesto o asociado puede ser agregado a
una lista
#pragma once
#include<iostream>
#include<string>

using namespace std;


class Contacto{
private:
string nombre;
int edad;
string distrito;
string universidad;
public:

10 | P á g i n a
Relaciones entre clases en C++
Abraham Sopla Maslucán

Contacto(string _nom, int _edad, string _distri, string _uni)


{
nombre = _nom;
edad = _edad;
distrito = _distri;
universidad = _uni;
}
//Seters y geters
//No implemento los seters y geters, por comodidad los valores de los
atributos los ingresaré mediante el constructor de la clase
//Solo el get del atributo edad para mostrar los estudiantes que tienen
entre 15 y 19 años
int getEdad()
{
return edad;
}

//Comportamiento
void muestraContacto()
{
cout << "Nombre: " << nombre << " Edad: " << edad << " Distrito: "
<< distrito << " Universidad: " << universidad << endl;
}
};
Agenda.h
Aquí se gestionan los objetos
#pragma once
#include<iostream>
#include<string>
#include "Contacto.h"
using namespace std;
class Agenda{
private:
int tamanio;
Contacto **listaContacto;
public:
Agenda() {
tamanio = 0;
listaContacto = NULL;
}
void agregaContacto(Contacto *_contacto)
{ //Realmente aquí se agregan los contactos a la agenda
Contacto **listaTemporal = new Contacto*[tamanio+1];
for (int i = 0; i < tamanio; i++)
{
listaTemporal[i] = listaContacto[i];
}
listaTemporal[tamanio] = _contacto;
tamanio += 1;
delete[] listaContacto;
listaContacto = listaTemporal;
}
void leeDatos()
{ //variables temporales
string tNombre;
int tEdad;
string tDistrito;
string tUniversidad;
cout << "Nombre : " << endl; cin >> tNombre;

11 | P á g i n a
Relaciones entre clases en C++
Abraham Sopla Maslucán

cout << "Edad : " << endl; cin >> tEdad;


cout << "Distrito : " << endl; cin >> tDistrito;
cout << "Universidad : " << endl; cin >> tUniversidad;

Contacto *otContacto=new Contacto(tNombre, tEdad, tDistrito,


tUniversidad);
//Agregacion
agregaContacto(otContacto);
}
void muestraListaContactos()
{
for (int i = 0; i < tamanio; i++)
{
listaContacto[i]->muestraContacto();
}
}
void muestraListaDe15a19()
{
for (int i = 0; i < tamanio; i++)
{
if(listaContacto[i]->getEdad()>=15 && listaContacto[i]-
>getEdad() <= 19)
listaContacto[i]->muestraContacto();
}
}
};

Principal.cpp
Se usa un menú para llamar a cada uno de los métodos de la clase contenedora
#pragma once
#include<iostream>
#include<string>
#include"Agenda.h"
using namespace std;
void main()
{
int opcion;
Agenda oa;
while (true)
{
cout << "1 agregar un dato "<<endl;
cout << "2 mostrar la lista de datos "<<endl;
cout << "3 mostrar la lista de estudiante de 15 a 19 años " << endl;
cout << "6 salir ... "<<endl;
cin >> opcion;
switch (opcion)
{
case 1:
oa.leeDatos();
break;
case 2:
oa.muestraListaContactos();
break;
case 3:
oa.muestraListaDe15a19();
break;
default:
exit(0);
}

12 | P á g i n a
Relaciones entre clases en C++
Abraham Sopla Maslucán

}
system("pause");
}

13 | P á g i n a
Relaciones entre clases en C++
Abraham Sopla Maslucán

Relación entre clases: generalización


(herencia)
Llamada también, herencia simple.

La generalización es un tipo de relación entre clases que permite compartir información entre dos
entidades para evitar la redundancia. El proceso que se sigue para implementar la generalización
se denomina herencia. El proceso inverso de la generalización por el cual se definen nuevas clases
a partir de otras ya existentes se denomina especialización, al proceso de implementación se le
denomina herencia múltiple.

Por ejemplo: las lavadoras, refrigeradoras, hornos de microondas, tostadoras, lavavajillas, etc.,
tienen características algunas características iguales, es decir todos son electrodomésticos. La
clase animal se divide en anfibios, mamíferos, insectos, pájaros, etc., y la clase vehículo en carros,
motos, camiones, buses, etc.

7. Herencia simple: un estudiante hereda las características de


una persona
Persona.h
#pragma once
#include<iostream>
#include<string>
using namespace std;
class Persona {
protected:
string nombre;
int edad;
public:
Persona() {}
Persona(string _nombre, int _edad)
{
nombre = _nombre;
edad = _edad;

14 | P á g i n a
Relaciones entre clases en C++
Abraham Sopla Maslucán

}
~Persona() {}
void muestraPersona()
{
cout << "Nombre: " << nombre << endl;
cout << "Edad: " << edad << endl;

};
Estudiante.h
#pragma once
#include<iostream>
#include<string>
#include "Persona.h"
using namespace std;
class Estudiante :public Persona {
private:
string codigo;
double nota;
public:
Estudiante() {}
Estudiante(string _nombre, int _edad, string _codigo, double
_nota):Persona(_nombre, _edad) {
codigo = _codigo;
nota = _nota;
}
~Estudiante() {}
void muestraEstudiante()
{
muestraPersona();
cout << "Codigo: " << codigo << endl;
cout << "Nota : " << nota << endl;
}
};
Principal.cpp
#pragma once
#include<iostream>
#include<string>
#include "Estudiante.h"
using namespace std;
void main()
{
//Estudiante oe1("Juan Perez", 16, "2018205", 16.8);

Estudiante *oe1;
oe1= new Estudiante("Juan Perez", 16, "2018205", 16.8);
oe1->muestraEstudiante();
system("pause");
}

8. Herencia simple: un automóvil es un vehículo, un camión


también

15 | P á g i n a
Relaciones entre clases en C++
Abraham Sopla Maslucán

#include <iostream>
using namespace std;
//Definición de clase base
class Vehiculo
{
private:
int canRuedas;
int capPasajeros;
public:
void setCanRuedas(int num)
{
this->canRuedas = num;
}

int getCanRuedas()
{
return this->canRuedas;
}

void setCapPasajeros(int num)


{
this->capPasajeros = num;
}
int setCapPasajeros()
{
return this->capPasajeros;
}
};

// Definición de una clase 'Camion' derivada de la clase base 'Vehiculo'.


class Camion : public Vehiculo
{
private:
/* Generalmente en 'private' se sitúan los datos miembros */
int carga; //en pies cúbicos
public:
void setCarga(int tamanio)
{
this->carga = tamanio;
}
int getCarga()
{
return this->carga;
}

16 | P á g i n a
Relaciones entre clases en C++
Abraham Sopla Maslucán

void Mostrar(void)
{
cout << "Ruedas: " << this->getCanRuedas() << endl;
cout << "Pasajeros: " << this->setCapPasajeros() << endl;
cout << "Capacidad de carga en pies cúbicos: " << this->getCarga()
<< endl;
}
};

/*
* Este enumerador sirve para definir diferentes tipos de automóvil
*/
enum tipo { deportivo, berlina, turismo };

// Definición de una clase 'Automovil' derivada de la clase base 'Vehiculo'.


class Automovil : public Vehiculo
{
private:
enum tipo tipoDeAutomovil;
public:
void setTipo(tipo t)
{
this->tipoDeAutomovil = t;
}

enum tipo getTipo(void)


{
return this->tipoDeAutomovil;
}

void Mostrar(void)
{
cout << "Ruedas: " << this->getCanRuedas() << endl;
cout << "Pasajeros: " << this->setCapPasajeros() << endl;
cout << "Tipo: ";

switch (this->getTipo())
{
case deportivo:
cout << "deportivo";
break;

case berlina:
cout << "berlina";
break;

case turismo:
cout << "turismo";
}
cout << endl;
}
};

int main(void)
{
Camion Camion1;
Camion Camion2;
Automovil Automovil1;

Camion1.setCanRuedas(18);
Camion1.setCapPasajeros(2);

17 | P á g i n a
Relaciones entre clases en C++
Abraham Sopla Maslucán

Camion1.setCarga(3200);

Camion2.setCanRuedas(6);
Camion2.setCapPasajeros(3);
Camion2.setCarga(1200);

Camion1.Mostrar();
cout << endl;
Camion2.Mostrar();
cout << endl;

Automovil1.setCanRuedas(4);
Automovil1.setCapPasajeros(6);
Automovil1.setTipo(berlina);

Automovil1.Mostrar();
system("pause");
return 0;
}

9. Herencia simple: un médico y un obrero son asalariados, un


asalariado es una persona

#include <iostream>
#include <string>
using namespace std;
//Definicion de la clase Persona
class Persona
{
protected:
string nombre;
int edad;
public:
Persona(string _nombre, int _edad) {
nombre=_nombre;
edad = _edad;
}
void setNombre(string _nom) { nombre=_nom; }
void muestraNombre(void) { cout << "Nombre: " << nombre << endl; }

18 | P á g i n a
Relaciones entre clases en C++
Abraham Sopla Maslucán

void setEdad(int _ed) { edad = _ed; }


void muestraEdad() { cout << "Edad: " << edad << endl; }
};

class Asalariado : public Persona {


protected:
double sueldo;
public:
Asalariado(string _nom, int _ed, double _suel):Persona(_nom, _ed){
setNombre(_nom);
setEdad(_ed);
sueldo = _suel;
}
void setSueldo(double _suel) { sueldo = _suel; }
void muestraSueldo() { cout << "Sueldo: " << sueldo << endl; }
};

class Obrero : public Asalariado {


private:
string cargo;
public:
Obrero(string _nom, int _ed, double _suel, string _car):Asalariado(_nom,
_ed, _suel) {
setNombre(_nom);
setEdad(_ed);
setSueldo(_suel);
cargo=_car;
}
void setCargo(char _car) { cargo=_car; }
void muestraCargo() { cout << "Cargo: " << cargo << endl; }

};

class Medico : public Asalariado {


private:
int cantpacientes;
public:
Medico(string _nom="Rojas", int _ed=58, double _suel=4200, int
_cant=20):Asalariado(_nom, _ed, _suel) {
setNombre(_nom);
setEdad(_ed);
setSueldo(_suel);
cantpacientes=_cant;
}
void setCantPacientes(int cant) { cantpacientes = cant; }
void muestraCantPacientes(void) { cout << "Cantidad de pacientes: " <<
cantpacientes << endl; }
};
//Probamos la clase.
int main()
{

Medico med1("Jesús Mejía", 40, 6500, 11);


cout << "********************" << endl;
med1.muestraNombre();
med1.muestraEdad();
med1.muestraSueldo();
med1.muestraCantPacientes();
cout << "********************" << endl;
Obrero ob1("José Manuel Corrales", 54, 1500.5, "Gasfitero");
ob1.muestraNombre();

19 | P á g i n a
Relaciones entre clases en C++
Abraham Sopla Maslucán

ob1.muestraEdad();
ob1.muestraSueldo();
ob1.muestraCargo();
cout << "********************" << endl;
Medico med2;
med2.muestraNombre();
med2.muestraEdad();
med2.muestraSueldo();
med2.muestraCantPacientes();
cin.get();
return 0;
}

Relación entre clases: herencia


(especialización)
Llamada también, eherencia múltiple.

10. Especialización: el hijo tiene dos apellidos, el primero del


padre y el segundo de la madre
// Un ejemplo de múltiples clases base
#include <iostream>
#include<string>
using namespace std;

class Papa {
protected:
string apellidoPapa;
double edad;

public:
void muestraApellidoPapa() {
cout << "Apellido Paterno: " << apellidoPapa <<endl;
}

20 | P á g i n a
Relaciones entre clases en C++
Abraham Sopla Maslucán

};

class Mama {
protected:
string apellidoMama;
public:
void muestraApellidoMama() {
cout << "Apellido materno: "<<apellidoMama <<endl; }
};

// Heredar multiples clases base.


class Hijo : public Papa, public Mama {
private:
string nombre;
public:
Hijo() {}
Hijo(string _nombre, string _apellidoPapa, string _apellidoMama)
{
nombre = _nombre;
apellidoPapa = _apellidoPapa;
apellidoMama = _apellidoMama;
}
void imprimeNombre()
{
cout << "Nombre : " << nombre<<endl;
}
};

int main()
{
Hijo *hijo1=new Hijo("Jose Manuel", "Mori", "Romero"); // proveida por
Derivada.
hijo1->imprimeNombre(); //desde hijo
hijo1->muestraApellidoPapa(); // desde Papa
hijo1->muestraApellidoMama(); // desde Mama
cin.get();
return 0;
}

Relación cíclica o reflexiva


11. Cíclica: un empleado puede ser jefe de otro empleado

Empleado.h Empleado
*
#pragma once
#include<string>
#include<iostream>

using namespace std; 0.


public class Empleado {
private:
.1
string nombre;
Empleado *jefe;
public:
Empleado() {}

21 | P á g i n a
Relaciones entre clases en C++
Abraham Sopla Maslucán

Empleado(string _nombre) {
nombre = _nombre;
}
Empleado(string nombre, Empleado *_jefe) {
this->nombre = nombre;
jefe = _jefe;
}
//Seter y Geter
void setNombre(string nombre) {
this->nombre = nombre;
}
string getNombre()
{
return nombre;
}
void setJefe(Empleado *_jefe)
{
jefe=_jefe;
}
Empleado * getJefe()
{
return jefe;
}
//Comportamiento
void imprimeJefe()
{
cout << "Empleado : "<<nombre <<" - No tiene jefe, puede ser
jefe"<<endl;
}
void imprimeEmpleado()
{
cout << "Empleado : " << nombre << " su jefe es: "<<jefe->getNombre()
<< endl;
}
};

Principal.cpp
#pragma once
#include<string>
#include<iostream>
#include "Empleado.h"

using namespace std;


void main()
{
Empleado *jefe1 = new Empleado("Pedro");
Empleado *jefe2 = new Empleado("Alberto");

Empleado *empleado3 = new Empleado("Carolina", jefe1);


Empleado *empleado4 = new Empleado("Luciana", jefe1);

cout << "Datos de los empleados " << endl;

jefe1->imprimeJefe();
jefe2->imprimeJefe();
empleado3->imprimeEmpleado();
empleado4->imprimeEmpleado();
system("pause");

22 | P á g i n a
Relaciones entre clases en C++
Abraham Sopla Maslucán

23 | P á g i n a
Relaciones entre clases en C++
Abraham Sopla Maslucán

Anexos:
12. Problema del diamante
El problema del diamante está representado en un conjunto de relaciones de herencia entre
cases donde: Una clase D hereda de B y C (Herencia múltiple), y las clases B y C heredan de A.

Caso 1: Si un método en D llama a un método definido en A, ¿por qué clase


lo hereda, ¿por B o por C?

Caso 2: Si invocamos desde D a un mètodo de B que tambièn existe en C.


¿Cuál de los metodos se ejecuta?

Gràfico 1. Problema del diamante1

1
Tomado de https://es.stackoverflow.com/questions/104165/por-qu%C3%A9-la-herencia-
m%C3%BAltiple-no-se-admite-en-java/104171

24 | P á g i n a
Relaciones entre clases en C++
Abraham Sopla Maslucán

13. Caso 1: Un atributo public


// Un ejemplo de herencia
#include <iostream>
#include<string>
using namespace std;
class Papa {
public:
string apellidoPapa;
public:
void muestraApellidoPapa() {
cout << "Apellido: " << apellidoPapa << "\n";
}
};

//Heredar .
class Hijo : public Papa {
public:
void setApellido(string _apellidoPapa)
{
apellidoPapa = _apellidoPapa;
}
};

int main()
{
Hijo hijo;
hijo.setApellido("Mori"); // proveída por Derivada.
//además estoy accediendo
al apellido directamente mediante el método
// desde Papa
hijo.apellidoPapa = "Asenjo";//Accediendo directamente al atributo
apellidoPapa
hijo.muestraApellidoPapa();
system("pause");
return 0;
}

14. Caso 2: un atributo protected


// Un ejemplo de herencia
#include <iostream>
#include<string>
using namespace std;
class Papa {
protected:
string apellidoPapa;
public:
void muestraApellidoPapa() {
cout << "Apellido: " << apellidoPapa << "\n";
}
};

//Heredar .
class Hijo : public Papa {
public:
void setApellido(string _apellidoPapa)
{
apellidoPapa = _apellidoPapa;
}
};

25 | P á g i n a
Relaciones entre clases en C++
Abraham Sopla Maslucán

int main()
{
Hijo hijo;
hijo.setApellido("Mori"); // proveida por Derivada.
//ademas estoy accediendo
al apellido directamente mediante el metodo
hijo.muestraApellidoPapa(); // desde Papa
system("pause");
return 0;
}

15. Caso 3: un atributo private


// Un ejemplo de herencia
#include <iostream>
#include<string>
using namespace std;
class Papa {
private:
string apellidoPapa;
public:
void setApellidoPapa(string _apellidoPapa)
{
apellidoPapa = _apellidoPapa;
}

string getApellidoPapa()
{
return apellidoPapa;
}

void muestraApellidoPapa() {
cout << "Apellido: " << apellidoPapa << "\n";
}
};

//Heredar .
class Hijo : public Papa {
public:
void setApellido(string _apellidoPapa)
{
setApellidoPapa(_apellidoPapa);
}
};

int main()
{
Hijo hijo;
hijo.setApellido("Mori"); // proveída por Derivada.
//además estoy accediendo al apellido
directamente mediante el método
hijo.muestraApellidoPapa(); // desde Papa
system("pause");
return 0;
}

16. Caso 4: Probando herencia pública, protegida y privada


Este es uno de los ejercicios más importantes para probar la el nivel de acceso de los atributos y
clases.

26 | P á g i n a
Relaciones entre clases en C++
Abraham Sopla Maslucán

En class Hijo : public Papa { - - };

 Primero: deje el nivel de acceso de la clase base en públic y cambie los niveles de acceso
del atributo apellidoPapa entre protected, public y private. También debe observar el
comportamiento en la función principal main.
 Segundo: deje el nivel de acceso de la clase base en protected y cambie los niveles de
acceso del atributo apellidoPapa entre protected, public y private. También debe
observar el comportamiento en la función principal main.
 Tercero: deje el nivel de acceso de la clase base en private y cambie los niveles de acceso
del atributo apellidoPapa entre protected, public y private. También debe observar el
comportamiento en la función principal main.
// Un ejemplo de herencia
#include <iostream>
#include<string>
using namespace std;

class Papa {
protected:
string apellidoPapa;
public:
void muestraApellidoPapa() {
cout << "Apellido: " << apellidoPapa << "\n";
}
};

//Heredar .
class Hijo : public Papa {
public:
void setApellido(string _apellidoPapa)
{
apellidoPapa = _apellidoPapa;
}
};

int main()
{
Hijo hijo;
hijo.setApellido("Mori"); // proveida por Derivada.
//ademas estoy accediendo
al apellido directamente mediante el metodo
hijo.muestraApellidoPapa(); // desde Papa
system("pause");
return 0;
}

17. Caso: superclase con nivel de acceso private


class Derivada : private Base { … }

"Cuando una clase base es heredada como 'private' sus miembros públicos se convierten en
miembros privados en la clase derivada."

En el siguiente código: class Derivada : private Base { … }; tenemos que cambiar private
a public para que el código compile sin problemas
// Este programa no compilara.

27 | P á g i n a
Relaciones entre clases en C++
Abraham Sopla Maslucán

#include <iostream>
using namespace std;

class Base {
private:
int a, b;
public:
void setAB(int _a, int _b) { a = _a; b = _b; }
void mostrarAB() { cout << a << " -- " << b << "\n"; }
};

// Miembros públicos de 'Base' son privados en 'Derivada'


class Derivada : private Base {
private:
int c;
public:

Derivada(int _c) { c = _c; }


void mostrarC() {
cout << c << "\n";
}
};

int main()
{
Derivada obj(30);
obj.setAB(10, 20); // Error, no se puede acceder _i set()
obj.mostrarAB(); // Error, no se puede acceder _i mostrar()
obj.mostrarC(); // Error, no se puede acceder _i mostrar()
cin.get();
return 0;
}

18. Caso: superclase con nivel de acceso protected


class Derivada : protected Base { … }
Un miembro privado de una clase base no es accesible directamente en cualquier otra parte de
su programa incluyendo desde cualquier subclase, sino mediante un set o get público. Sin
embargo, los miembros protegidos sí pueden ser accedidos directamente desde otras subclases.
Cuando una clase base es heredada como pública, los miembros protegidos en la clase base se convierten en
miembros protegidos en la clase derivada, y 'son' accesibles en la clase derivada o subclase. Además, usando
'protected' usted puede crear miembros de clases que son privados para su clase, pero que aun
asi pueden ser heredados y accedidos por una clase derivada.
#include <iostream>
using namespace std;
class Base {
protected:
int a, b; // privados _a Base, pero accesibles _a Derivada.
public:
void set(int _a, int _b) { a = _a; b = _b; }
void mostrarAB() { cout << a << " " << b << "\n"; }
};

class Derivada : protected Base {


int c;
public:
// Derivada puede accesar en Base _a 'b' e 'a'
void setC() { c = a * b; }

28 | P á g i n a
Relaciones entre clases en C++
Abraham Sopla Maslucán

void mostrarC() { cout << c << "\n"; }


};

int main()
{
Derivada obj;

obj.set(2, 3); // OK, conocido por Derivada.


obj.mostrarAB(); // OK, conocido por Derivada.

obj.setC();
obj.mostrarC();
cin.get();
return 0;
}

19. Caso 5: un almacén tiene cuenta y puede estar asociado a


cliente

Con el modelo que implementamos en la solución se puede gestionar por separado:

 una lista de clientes,


 una lista de cuentas,
 una lista de almacenes asociados a clientes,
 una lista de almacenes compuestos a cuentas
 Una lista de almacenes con cuentas y clientes a la vez

La característica más importante de este desarrollo es que cuando se elimina un almacén se


elimina una cuanta. Y cuando se elimina un almacén no se elimina un cliente

Cuenta.h
#include<iostream>
#include<string>
using namespace std;
class Cuenta {
private:
int nroCuenta;
public:
Cuenta() {} //No se puede asignar valores a los atributos
~Cuenta() {}

29 | P á g i n a
Relaciones entre clases en C++
Abraham Sopla Maslucán

void setNroCuenta(int _nroCuenta) { nroCuenta = _nroCuenta; }


int getNroCuenta() { return nroCuenta; }
//comportamiento
void muestraCuenta()
{
cout << "Nro de cuenta: " << nroCuenta << endl;
}
};

Cliente.h
#include<iostream>
#include<string>
using namespace std;
class Cliente {
private:
string nombre;
public:
Cliente() {}
Cliente(string _nombre) {
nombre = _nombre;
}
~Cliente() {}

void setNombre(string _nombre) { nombre = _nombre; }


string getNombre() { return nombre; }

//Comportamiento
void muestraCliente()
{
cout << "Nombre: " << nombre << endl;
}
};

Almacen.h
//En el almacen siempre registramos cuenta aunque no cliente o los dos juntos
//Podemos crear una lista de clientes
//Podemos crear una lista de cuentas
//Podemos crear una lista de almacenes
//Siempre que se crea un almacen se crea una cuenta si o si
//Siempre que se crea un almacen se crea una cuenta si o si, y si quieres puedes
incluir un cliente
//Cuando borras un almacen se borra una cuenta pero no el cliente
#include<iostream>
#include<string>
#include"Cuenta.h"
#include"Cliente.h"
using namespace std;
class Almacen {
private:
Cuenta *cuenta;
Cliente *cliente;
public:
//Acceder a una cuenta con get
Almacen() {
cuenta = new Cuenta();
}
//Por si quiera agregar los atributos objeto al instante de crear almacen
//En los tres constructores asignamos una direcion de un objeto cuenta al
atributo cuenta

30 | P á g i n a
Relaciones entre clases en C++
Abraham Sopla Maslucán

//En el segundo constructor solo asignamos el atributo cuenta y no cliente


Almacen(Cuenta *_cuenta)
{
cuenta = _cuenta;
}
//En el tercer constructor asignamos el atributo cuenta y cliente a la vez
Almacen(Cuenta *_cuenta, Cliente *_cliente)
{
cuenta = _cuenta;
cliente = _cliente;
}
//Elimino cuenta pero no almacen
~Almacen() {
delete cuenta;
}
//Seter y geter
void setCuenta(Cuenta *_cuenta)
{
cuenta = _cuenta;
}
Cuenta * getCuenta()
{
return cuenta;
}
void setCliente(Cuenta *_cliente)
{
cuenta = _cliente;
}
Cliente * getCliente()
{
return cliente;
}

//Por si quiera asignar objetos a los dos atributos a la vez mediante seter
y geters
void setCuentaCliente(Cuenta *_cuenta, Cliente *_cliente)
{
cuenta = _cuenta;
cliente = _cliente;
}

//Comportamientos
void muestraDatos()
{
cout << "Cuenta : " << cuenta->getNroCuenta() << " Nombre: "<<cliente-
>getNombre()<<endl;
}
};

Principal.cpp
//En el almacen siempre registramos cuenta aunque no cliente o los dos juntos
//Podemos crear una lista de clientes
//Podemos crear una lista de cuentas
//Podemos crear una lista de almacenes
//Siempre que se crea un almacen se crea una cuenta si o si
//Siempre que se crea un almacen se crea una cuenta si o si, y si quieres puedes
incluir un cliente
//Cuando borras un almacen se borra una cuenta pero no el cliente
#include<iostream>
#include<string>

31 | P á g i n a
Relaciones entre clases en C++
Abraham Sopla Maslucán

#include "Almacen.h"

using namespace std;


void main()
{
Almacen *almacen1 = new Almacen();
//accedemos a la cuenta a traves de almacen1
almacen1->getCuenta()->setNroCuenta(1234);
Cuenta *cuenta1=new Cuenta();
cuenta1= almacen1->getCuenta();

Cliente *cliente1=new Cliente("Juan Perez");


almacen1->setCuentaCliente(cuenta1, cliente1);
//Mostrando todos los datos
cout << "Mostrando los datos " << endl;
almacen1->muestraDatos();

cout <<"\nEliminamos el objeto almacen" << endl;


//Eliminamos el objeto cuenta
delete almacen1;

cout <<"\nLos datos del cliente siguien existiendo" << endl;


cliente1->muestraCliente();
cout <<"\nLos datos de la cuenta ya no existen " << endl;
cuenta1->muestraCuenta();
system("pause");
}

32 | P á g i n a
Relaciones entre clases en C++
Abraham Sopla Maslucán

Referencias
Deitel, P. J. & Deitel, H. M. (2008). Como programar en Java, 6ta edición. Pearson
Educación: México.
Laza, R. y García, B. (2008). Metodología y tecnología de la programación. Pearson
Educación: México.
Mañas, J. A. (2010). Java vademécum. Departamento de Ingeniería de Sistemas
Telemáticos, Universidad Politécnica Madrid, España.
Moltó, G. (S/A). Conceptos de java para estructuras de datos. Escuela Técnica
Superior de Ingeniería Informática, Universidad Politécnica de Valencia,
España.
Cibertec. (S/A). Algoritmos y estructura de datos – TI. Cibertec, Perú.
Wikibooks (2018) Programación en C++/Herencia. Recuperado el 10 de setiembre
de 2018 de
https://es.wikibooks.org/wiki/Programaci%C3%B3n_en_C%2B%2B/H
erencia

33 | P á g i n a

También podría gustarte