Está en la página 1de 11

UACJ/IIT Clase #12

Departamento: Eléctrica y Computación Herencia y Constructores


Materia: Programación orientada a objetos
Maestra: Sandra Ramírez Lara Fecha:
sramirez@uacj.mx
Nombre: Correo:
Matricula:

Objetivos:

 Comprender la relación de herencia entre diversas clases durante el proceso de creación de un objeto a partir de
una subclase y el orden de las llamadas a partir del constructor de la clase base y el de los constructores subsecuentes de las
clases heredadas
 Identificar cual es el orden en el que se ejecutan los constructores y destructores en base a su jerarquía, así como los tipos
de acceso que podemos implementar en las clases heredadas

Preguntas inicializadoras:
1
2
3
4

Introducción

Partiendo de que Un constructor es una función miembro que automáticamente es llamada cuando el objeto de la clase es creada o
instanciada y que los constructores son funciones miembro especiales que sirven para inicializar un objeto de una determinada clase en
el momento que se declara, no debemos olvidar que los constructores tienen el mismo nombre que la clase, no retornan ningún valor y
no pueden ser heredados.

Los constructores se pueden clasificar en constructores sin parámetros y con parámetros, un constructor por defecto se clasifica como
constructor sin parámetros, un constructor copia se puede considerar como un constructor con paramentos.

Constructores en herencia
Teniendo en cuenta que contamos con el mecanismo de herencia, el cual nos permite la reusabilidad de código y que en base a esta
propiedad podemos definir un tipo de dato de orden superior (clase padre o clase base, super clase) y a partir de estos podemos definir
datos derivados de clases de segundo nivel (clases derivadas, hijas o secundarias o sub clases), permitiéndonos la creación de modelos
y relaciones entre clases y diferentes tipos de jerarquías de herencia definidas para dar solución a problemas
Los constructores son métodos especiales que permiten definir la implementación para el estado inicial de creación de una instancia de
un objeto. La definición de un constructor, a diferencia de los métodos comunes es que no debe especificar el tipo de dato de retorno y
se identifican con el mismo nombre de la clase.
Debemos de recordar que para las clases base se debe declarar sus propios constructores. Y estos no se pueden heredar a las subclases,
sin embargo, desde una subclase se puede invocar los constructores de la clase base.
Esto implica que se requiere redefinir los constructores en La clase heredada y que se tiene que hacer explícitamente
Proceso de creación
1. Se crea la clase base y su constructor
2. Se crea una clase heredada con su constructor y llamando al constructor de la clase base
3. se crea un objeto de una clase heredada o derivada
4. se invoca al constructor de la clase base
5. se invoca al constructor de la clase derivada.

Si la clase base es a su vez una clase derivada, el proceso se repite recursivamente.


Si no hemos definido los constructores de las clases, se usan los constructores por defecto que crea el compilador.

Cuando queremos inicializar las clases base usando parámetros desde el constructor de una clase heredada o derivada lo haremos de
modo como lo hacemos con los datos miembro, usaremos el constructor de la clase base con los parámetros adecuados.

si en una subclase se omite la construcción base después de la firma del constructor sin parámetros, se invoca el mismo constructor (sin
parámetros) de la clase base.

TIPOS DE ACCESO al declarar una clase heredada

Destructores en herencia

Un destructor es una función miembro que se invoca automáticamente cuando el objeto queda fuera del alcance o es destruido
explícitamente por una llamada a eliminar. Un destructor tiene el mismo nombre que la clase, precedido por una tilde (~). Por ejemplo,
el destructor para la clase String se declara: ~ String ().

Si no define un destructor, el compilador proporcionará uno por defecto; Para muchas clases esto es suficiente. Solo necesita definir un
destructor personalizado cuando la clase almacena los manejadores de los recursos del sistema que deben liberarse o los punteros que
poseen la memoria a la que apuntan (memoria dinámica)

Orden de destrucción
Cuando un objeto queda fuera del alcance o se elimina, la secuencia de eventos en su destrucción completa es la siguiente:

 Se llama al destructor de la clase y se ejecuta el cuerpo de la función del destructor.


 Los destructores para objetos miembros no estáticos se llaman en el orden inverso en el que aparecen en la declaración de
clase. La lista de inicialización de miembros opcional utilizada en la construcción de estos miembros no afecta el orden de
construcción o destrucción.
 Los destructores para las clases base no virtuales se llaman en el orden inverso de la declaración.
Los destructores para las clases base virtuales se llaman en el orden inverso de la declaración
Declarando destructores
Los destructores son funciones con el mismo nombre que la clase, pero precedidas por una tilde (~)

Los destructores se llaman cuando ocurre uno de los


siguientes eventos:
las situaciones en las que el compilador llama
automáticamente al destructor:

 Cuando se llama a un operador de eliminación.


 Cuando finaliza la ejecución del programa.
 Cuando finaliza el bloque / alcance de las variables
locales.
 El destructor se llama explícitamente utilizando el
nombre completo de la función del destructor.

Los destructores pueden llamar libremente a las funciones de


los miembros de la clase y acceder a los datos de los
miembros de la clase.

No se puede declarar como constante, volátil o estático. Sin


embargo, se pueden invocar para la destrucción de objetos
declarados como const, volatile o static.

Puede ser declarado como virtual. Con los destructores


virtuales, puede destruir objetos sin saber su tipo: el
destructor correcto para el objeto se invoca mediante el
mecanismo de la función virtual. Tenga en cuenta que los
destructores también se pueden declarar como funciones
virtuales puras para clases abstractas.

Hay dos restricciones en el uso de destructores:

 No puedes tomar su dirección.


 Las clases derivadas no heredan el destructor de
su clase base.
Caso 1 constructores por defecto en herencia de clases Notas

#include <iostream>
using namespace std; Al crear un objeto de una clase heredada
primero se construye lo heredado en este caso
class Clase1 el dato1 y luego los propios atributos de la clase
{ derivada en este caso el dato 2
protected:
int dato1; El objeto creado en base a la clase 2 tiene
public: acceso a:

2 atributos el propio y el heredado


Clase1( ) : dato1(1) Clase1(int a) : dato1(a) 3 métodos su constructor, la función
leerclase2() y la función leerclase1() heredada

{
cout << "Constructor de Clase1" << endl;
}
int Leerclase1() {return dato1; }
};

class Clase2 : public Clase1


{
protected:
int dato2;

public:
Clase2() : dato2(2) Clase2(int a, int b) : Clase1(a), dato2(b)
{
cout << "Constructor de Clase2" << endl;
}

int Leerclase2() { return dato2; }

};

int main()
{
Clase2 objeto;

cout << "dato = " << objeto.Leerclase1() <<endl;


cout << "dato = " << objeto.Leerclase2() << endl;

return 0;
}
Caso 2 inicialización de clases bases y heredadas en Notas
constructores

#include <iostream>
using namespace std; Para poder inicializar el dato heredado, necesitamos redefinir el
constructor predeterminado tomando en cuenta los datos
class Clase1 { heredados
protected:
int dato1; //5
public:
Clase1(int a) : dato1(a) // constructor con parametros
{
cout << "Constructor de clase1" << endl;
}

int Leer1() { return dato1; }


};

class Clase2 : public Clase1 {


protected:
int dato2; //15

public:
Clase2(int a, int b) : Clase1(a), dato2(b) // con paramaetros por
lo que esta redefiniendo al constructor de la clase base
{ //5 15
cout << "Constructor de clase2" << endl;
}
int Leer2() { return dato2; }

};

int main() {
Clase1 objeto1(10);
// Clase2 objeto2(5,15);

cout <<"Dato1 = " << objeto1.Leer1() <<endl;


// cout <<"Dato1 = " << objeto2.Leer1() <<endl;
// cout <<" Dato2 = " <<objeto2.Leer2() << endl;

return 0;
}
Actividades

Actividad 1

Analizar, modificar completar los códigos y preguntas

Codigo incompleto Codigo Con Constructor Conteste las preguntas

#include <iostream> 1. En el codigo se aplica la propiedad de la herencia?


using namespace std;
2. Que errores se generan en el codigo original?
class par
{ 3. Cuantos constructores se requieren?
public:
int a, b; 4. Como se le llama que las funciones tienen el mismo nombre
public: y no se presentan problemas de ambigüedad
// Constructores ¿
5. Desarrolle los cambios necesarios en el programa que se
construyan los objetos
};

int main()
{
int x=2, y=8;
par par1;
par par2(x,y);

cout << "Valor de


par1.a: " << par1.a << endl;
cout << "Valor de
par1.b: " <<par1.b << endl;
cout << "Valor de
par2.a: " << par2.a << endl;
cout << "Valor de
par2.b: " <<par2.b << endl;
par1 = par2;
cout << "Valor de
par1.a: " << par1.a << endl;
cout << "Valor de
par1.b: " <<par1.b << endl;

return 0;
}
Actividad 2

Analice el código y conteste las preguntas

Código Contestar preguntas

#include <iostream>
using namespace std; 1. Conectar la línea de código con la acción

class ClaseA {
public:
Cuál es el orden de creación y destrucción de objetos
ClaseA() : datoA(10) {
cout << "Constructor de A" << endl;
} Análisis:
~ClaseA() { cout << "Destructor de A" << endl; }
int LeerA() const { return datoA; } Tenemos dos clases

protected: Se crea un objeto de la clase derivada


int datoA;
}; Por lo que primero llamara al constructor de la clase base

class ClaseB : public ClaseA { Se llama al constructor propio


public:
ClaseB() : datoB(20) {
Para liberarse se hace el proceso inverso
cout << "Constructor de B" << endl;
}
~ClaseB() { cout << "Destructor de B" << endl; } Se destruye desde la clase derivada
int LeerB() const { return datoB; }
Luego se destruye de la clase base
protected:
int datoB; 1. Que tipos de constructores tiene la clase A
}; 2. Qué tipo de constructor tiene la clase b
3. Cuales constructores son invocados desde el main()
int main() {
ClaseB objeto;

cout << "a = " << objeto.LeerA() << ", b = "


<< objeto.LeerB() << endl;

return 0;
}
Actividad 3

Cambie la función inicializadora por un constructor

Código Código modificado

#include <iostream>
using namespace std;

class base {

protected:
int i, j;

public:

void set(int a, int b)


{
i = a;
j = b;
}

void mostrar()
{
cout << i << " " << j << "\n";
}

};

// j e i se heredan como 'protected'


class derivada1 : public base {
int k;

public:
void setk()
{
k = i*j;
}
void mostrark() { cout << k << "\n"; }
};

// j e i se heredan indirectamente a través de derivada1


class derivada2 : public derivada1 {
int m;

public:
void setm() { m = i-j; }
void mostrarm() { cout << m << "\n"; }
};

int main()
{

derivada1 obj1;
derivada2 obj2;
obj1.set(2, 3);
obj1.mostrar();
obj1.setk();
obj1.mostrark();

// obj2 de la clase derivada2 tiene acceso a 'i' y 'j', puesto que la


clase hereda
// tal como la clase derivada1, los miembros protegidos de la
clase base.

obj2.set(3, 4);
obj2.mostrar();
obj2.setk();
obj2.setm();
obj2.mostrark();
obj2.mostrarm();

return 0;
}

class base class derivada1 : public base class derivada2 : public derivada1

aatributos int i, j; protected int k; private int m; private

j e i se heredan como 'protected' i , j, k se heredan como

metodos void set(int a, int b) void setk() void setm()

void mostrar() void mostrark() void mostrarm()

se heredan de la clase base se heredan de la clase derivada1

void set(int a, int b) void setk()

void mostrar() void mostrark()

que a su vez heredan de la clase base

void set(int a, int b)

void mostrar()

Actividad 4

Analice el código, ejecútelo, conteste las preguntas, Explique

Código Conteste preguntas

#include <iostream>
#include <cstring>
using namespace std; 1. Cuantos métodos tiene la clase
2. Cuantos constructores tiene la clase
class cadena 3. Cuantos destructores tiene la clase
{
public: Explique a grades rasgos lo que hace el programa
cadena(); // Constructor por defecto
cadena(const char *c); // Constructor desde cadena c
cadena(int n); // Constructor de cadena de n caracteres
cadena(const cadena &); // Constructor copia
~cadena(); // Destructor

void Asignar(const char *dest);


char *Leer(char *c);
private:
char *cad; // Puntero a char: cadena de caracteres
};

// metodos de la clase definidos ouline


cadena::cadena() : cad(NULL) {}

cadena::cadena(const char *c)


{
cad = new char[strlen(c)+1];// Reserva memoria
para cadena
strcpy(cad, c); // Almacena la cadena
}

cadena::cadena(int n)
{
cad = new char[n+1]; // Reserva memoria para n
caracteres
cad[0] = 0; // Cadena vacía
}

cadena::cadena(const cadena &Cad)


{
// Reservamos memoria para la nueva y la
almacenamos
cad = new char[strlen(Cad.cad)+1];
// Reserva memoria para cadena
strcpy(cad, Cad.cad); // Almacena la cadena
}

cadena::~cadena()
{
delete[] cad; // Libera la memoria reservada a
cad
}

void cadena::Asignar(const char *dest)


{
// Eliminamos la cadena actual:
delete[] cad;
// Reservamos memoria para la nueva y la
almacenamos
cad = new char[strlen(dest)+1];
// Reserva memoria para la cadena
strcpy(cad, dest); // Almacena la cadena
}

char *cadena::Leer(char *c)


{
strcpy(c, cad);
return c;
}
int main() {
cadena Cadena1("Cadena de prueba");
cadena Cadena2(Cadena1); // Cadena2 es copia de Cadena1
cadena *Cadena3; // Cadena3 es un puntero
char c[256];

// Modificamos Cadena1:
Cadena1.Asignar("Otra cadena diferente");
// Creamos Cadena3:
Cadena3 = new cadena("Cadena de prueba 3");

// Ver resultados
cout << "Cadena 1: " << Cadena1.Leer(c) << endl;
cout << "Cadena 2: " << Cadena2.Leer(c) << endl;
cout << "Cadena 3: " << Cadena3->Leer(c) << endl;

delete Cadena3; // Destruir Cadena3.


// Cadena1 y Cadena2 se destruyen automáticamente

return 0;
}

Actividad 5

Conclusiones

Actividad 5

Investigue Fuentes bibliográfica

Liga contenido
https://docs.microsoft.com/en-us/cpp/cpp/constructors-cpp?view=vs-2019
C Con Clase | Curso C++ (cap30)
http://informatica.utem.cl/~mcast/ESDATOS/RESPALDO/POO-C++-IV-2.ppt

También podría gustarte