Descarga la aplicación para disfrutar aún más
Vista previa del material en texto
Laboratorio de Programación II Página 55 Mgter. Ángel Montesinos Sesión N° 03 UNIVERSIDAD CATÓLICA DE SANTA MARÍA PROGRAMA PROFESIONAL DE INGENIERÍA DE SISTEMAS SESIÓN N° 05: Autorreferencias, Constructores, Destructores y Objetos Miembros de Clase I OBJETIVOS ❖ Aplicar en la construcción de programas las estructuras y sus recursos para la manipulación, organización y almacenamiento de datos. ❖ Diseñar programas con eficiente manipulación y organización de datos. ❖ Revisar los conceptos involucrados en los temas de estructuras. ❖ Evaluar los conocimientos de los alumnos en estructuras. II TEMAS A TRATAR ❖ Introducción. ❖ referencias ❖ Constructores ❖ Destructores ❖ ¿Cómo se declara un objeto como miembro de clase? ❖ Inicialización de miembros de clase ❖ Resumen III MARCO TEORICO 1. INTRODUCCIÓN La Programación Orientada a Objetos ofrece recursos muy versátiles para la manipulación de objetos, además, en cada lenguaje de programación se ofrecen recursos adicionales que le ponen el sello particular de optimización al diseño del código; una de estos recursos son las auto referencias, el uso de las mismas permite el encadenamiento en la llamada de los métodos, recursos que puede resultar un tanto extraños para un programador novato, pero ofrecen simplicidad y ahorro de líneas de código en su uso para la codificación. Las referencias fueron introducidas en Lenguaje C++ como una forma de hacer uso de recursos(variables) mediante un alias con implicaciones de uso directo de memoria, un recurso que pretende simplificar el uso de punteros pero no deja de lado el uso directo recurso almacenado en memoria. A parte de las referencias debemos hacer uso del puntero implícito this, un puntero de dichas características se usa al interior de la declaración de clase para hacer referencia al objeto que envía el mensaje y para el cual se ejecuta el método. El proceso de diseñar una clase con lleva la idea de crear un nuevo tipo de dato para una aplicación que tendrá características que no poseen los tipos de datos primitivos ni agregados existentes, la principal tarea es la de proveer un conjunto determinado de atributos y métodos que de forma completa nos proporcionen la forma de representar una entidad concreta; al crear los objetos que pertenecen a dicha clase se pasa por tres fases bien definidas, la primera es la instanciación del objeto, en donde se le asigna el espacio en memoria al objeto en creación, la segunda es la asignación de recursos, en donde se provee recursos de memoria o de algún tipo especial a Laboratorio de Programación II Página 56 Mgter. Ángel Montesinos Sesión N° 03 atributos como punteros o manejadores de archivos y la tercera es la iniciación, donde se debe garantizar que los objetos aparezcan en la aplicación con los valores correctos. [ 1 ][ 2 ] Los constructores llevan a cabo estas tres labores, es tan importante su ejecución que de carecer de un constructor definido por el programador, el compilador asigna uno llamado implícito, normalmente los constructores son invocados al momento de crear el objeto, dicha invocación se hace de forma implícita, pero también es posible que el programador los invoque explícitamente. Los destructores llevan a cabo el proceso contrario a los destructores, están encargados de hacer que los objetos creados sean adecuadamente eliminados de la aplicación, este punto se refiere al punto donde los objetos dejan de tener sentido, que normalmente es cuando se abandona el ámbito de creación del objeto, eso implica además que si el objeto tiene recursos de memoria dinámica asignados deben ser liberados por un destructor explícito que se encargue de ello, los constructores llevan a cabo el proceso de liberar todos los recursos ocupados por el objeto en su creación y existencia. El lenguaje C++ está diseñado de tal forma que podamos construir representaciones bastante complejas de la realidad que modelamos en los programas; si pensamos en términos de Programación Orientada a Objetos nos daremos cuenta que el mundo real es más complejo de lo que a veces conceptualizamos mediante las clases, por ejemplo la mayor parte de objetos es parte de otro objeto, es decir que en la definición de una clase tendremos como miembro dato a un objeto de otra clase, este fenómeno se representa en términos de los conceptos de agregación y composición, aunque al escribir el código no existe una diferencia práctica en la representación de ambas propiedades si embargo en el proceso de análisis es vital hacer la diferencia porque de esa forma se concibe la naturaleza de la clase que se modela y la forma como se conciben los objetos. [ 1 ][ 2 ] El incluir como atributo miembro de una clase a un objeto nos enfrentamos a cierto número de requerimientos de funcionamiento de las aplicaciones, el primero se refiere a la propiedad de lenguaje C++ que exige que cualquier identificador usado para declarar un recurso debe estar previamente declarado en el programa, esto nos lleva a considerar que si construimos una clase con un objeto de otra clase como miembro dicha clase, se debe tener previamente declarada la clase de la cual declaramos al objeto como miembro y el nombre de dicha clase debe estar al alcance dentro del ámbito de definición de nuestra clase compuesta, al hacer definiciones de clases en archivos independientes de cabecera debemos colocar una instrucción include que nos permita el acceso a dicho archivo de cabecera; El segundo aspecto se refiere a la forma como debemos inicializar al objeto miembro, esto es complicado porque no podemos hacer que los constructores del objeto miembro sean invocados de forma explícita, por lo que usaremos listas de inicialización para que los constructores del objeto sean adecuadamente provistos de los parámetros de inicialización. 2. REFERENCIAS Las referencias son recursos que se usan como un identificador alternativo para un objeto. El principal uso que se les aplica es para enviar objetos como parámetros de métodos y como valores de retorno, tanto en funciones como en la sobrecarga de operadores. De forma general la notación &x se lee como referencia a x. [ 1 ][ 2 ] La forma de hacer uso de las referencias es la siguiente: int variableEntera = 0; float variableFlotante = 0; int& referenciaVariableEntera; referenciaVariableEntera = variableEntera; float& referenciaVariableFlotante = variableFlotante; La referencia se declara anteponiéndole el operador & al nombre de la referencia, al igual que con los punteros la referencia debe de ser del mismo tipo del recurso referenciado. Inicializar la referencia significa que ha sido ligada a un objeto dato y a partir de ese momento actúa como si fuera un alias del recurso, es decir que si queremos manipular el recurso podemos hacerlo mediante su identificador inicial o por medio de la referencia. En el ejemplo se aprecia que una vez declarada la referencia a ésta se le asigna el nombre de la variable. La otra forma se en la que se define es asignándole la variable al momento de la declaración. [ 1 ][ 2 ] Una vez inicializada la referencia se puede manipular la variable referenciada a través de la misma: Laboratorio de Programación II Página 57 Mgter. Ángel Montesinos Sesión N° 03 // igual que variableEntera = 3 referenciaVariableEntera = 3; // igual que variableFlotante = 6.3 referenciaVariableFlotante = 6.3 A. PUNTERO IMPLÍCITO THIS El recurso es utilizado para hacer referencia al objeto para el cual fue invocado el método, se dice que es implícito porque no es necesario incluirlo en la especificación de código pero el puntero está presente, su forma de uso es la siguiente: // Codigo 3.01: practica3_01.cpp // demostración deluso del puntero implícito this. #include <iostream> using namespace std; classClase { int variableEntera; float variableFlotante; public: Clase() { variableEntera = 0; variableFlotante = 0; } int getVariableEntera() { return this -> variableEntera; } float getVariableFlotante() { return this -> variableFlotante; } }; int main() { Clase objeto; cout << objeto.getVariableEntera() << endl; cout << objeto.getVariableFlotante() << endl; system("pause"); return 0; } Se puede apreciar que en los métodos de la clase se hace uso del puntero implícito this, pero sin embargo si no se coloca no hay ninguna diferencia, el puntero se refiere al objeto que invoca al método en este caso a objeto. B. AUTO REFERENCIAS Las autoreferencias se aplican para encadenar métodos para su ejecución, algunas veces resulta muy interesante llamar a ejecución a un conjunto de métodos los cuales retornan una referencia al objeto de clase que se está usando para llamar a la operación, un ejemplo sería el siguiente: // Codigo 3.02: practica3_02.cpp // demostración del uso de las autoreferencias. #include <iostream> using namespace std; Laboratorio de Programación II Página 58 Mgter. Ángel Montesinos Sesión N° 03 class Clase { int variableEntera; float variableFlotante; public: Clase() { variableEntera = 0; variableFlotante = 0; } int getVariableEntera() { return this -> variableEntera; } float getVariableFlotante() { return this -> variableFlotante; } Clase& sumaEntero(int n) { variableEntera += n; return *this; } Clase& sumaFlotante(float n) { variableFlotante += n; return *this; } }; int main() { Clase objeto; cout << objeto.getVariableEntera() << endl; cout << objeto.getVariableFlotante() << endl; objeto.sumaEntero(5).sumaFlotante(3.5); cout << objeto.getVariableEntera() << endl; cout << objeto.getVariableFlotante() << endl; system("pause"); return 0; } Cuando tenemos un grupo de métodos que se utilizan para modificar el estado del objeto y generalmente no tienen un valor de retorno, podemos hacer que dicho valor de retorno sea una referencia al objeto de la clase, en este caso ese objeto de la clase del que hablamos es manejado a través del puntero implícito this, que es el que finalmente se devuelve, bajo este esquema podemos encadenar los métodos para su ejecución como se muestra en el ejemplo. 3. CONSTRUCTORES Son métodos especiales encargados de la adecuada creación de los objetos, se invocan implícitamente al crear un objeto, llevan el mismo nombre de la clase y no devuelven valores de retorno ni los especifican; una clase puede tener tantos constructores como formas de iniciar objetos necesite. Si la clase no tiene un constructor proporcionado por el programador el compilador le proporciona uno, pero se corre el riesgo de que no inicialice los atributos de los objetos instanciados, como ejemplo el siguiente cñodigo: // Codigo 3.03: practica3_03.cpp // demostración del uso de las autoreferencias. #ifndef CLASEEJEMPLO_H #define CLASEEJEMPLO_H Laboratorio de Programación II Página 59 Mgter. Ángel Montesinos Sesión N° 03 class ClaseEjemplo { private: int atributoEntero; char atributoChar; public: ClaseEjemplo(int i) { atributoEntero = i; atributoChar = ' '; } ClaseEjemplo(int i = 0, char c = ' ') { atributoEntero = i; atributoChar = c; } void mostrar() { cout << "atributoEntero: " << atributoEntero << endl; cout << "atributoChar: " << atributoChar << endl; } }; #endif La clase anterior registra dos constructores el segundo constructor usa parámetros por defecto, el primero debe diferenciarse del segundo en la lista de argumentos, no colocar argumentos en el primero causaría ambigüedad en la llamada implícita. // Codigo 3.04: practica3_04.cpp // demostración del uso de las autoreferencias. #ifndef OTRACLASEEJEMPLO_H #define OTRACLASEEJEMPLO_H class OtraClaseEjemplo { private: int atributoEntero; char atributoChar; public: void mostrar() { cout << "atributoEntero: " << atributoEntero << endl; cout << "atributoChar: " << atributoChar << endl; } }; #endif Esta segunda clase carece de constructor explícito, al instanciar objetos los atributos no reciben valores y se inicializan con los valores existentes en las posiciones de memoria que les asignen. // Codigo 3.05: practica3_05.cpp // demostración del uso de las autoreferencias. #include <iostream> using namespace std; #include "claseejemplo.h" #include "otraclaseejemplo.h" int main() { ClaseEjemplo objetoUno; Laboratorio de Programación II Página 60 Mgter. Ángel Montesinos Sesión N° 03 ClaseEjemplo objetoDos(4,'e'); OtraClaseEjemplo objetoTres; cout << "objetoUno: " << endl; objetoUno.mostrar(); cout << "objetoDos: " << endl; objetoDos.mostrar(); cout << "objetoTres: " << endl; objetoTres.mostrar(); system("pause"); return 0; } El objetoTres no tiene sus atributos inicializados correctamente como se mostrará en la impresión. C. INVOCACIÓN DE CONSTRUCTORES Los constructores se invocan implícitamente al construir los objetos: // Invocación implícita del constructor ClaseEjemplo objetoUno; // Error: invocación ilegal del constructor ClaseEjemplo::ClaseEjemplo(); // Error: invocación ilegal del constructor ClaseEjemplo objetoDos = ClaseEjemplo::ClaseEjemplo(6, 'o'); // Invocación legal del constructor ClaseEjemplo objetoTres = ClaseEjemplo(9, 'i'); // Variación sintáctica del anterior ClaseEjemplo objetoCuatro(3, 'h'); Si queremos objetos dinámicos se debe de poder crearlos mediant el operador new y punteros a objetos del mismo tipo. { ClaseEjemplo *ptrObjetoUno = new ClaseEjemplo; ClaseEjemplo *ptrObjetoDos = new ClaseEjemplo(4,'x'); } Es necesario recalcar que al salir del bloque los punteros son destruidos mas no así los objetos dinámicos que referencian. D. PROPIEDADES DE LOS CONSTRUCTORES Los constructores son métodos especiales por lo tanto no tienen el mismo tipo de propiedades de los métodos convencionales: ▪ Los constructores siempre tienen el mismo nombre de la clase a la que pertenecen. ▪ No se pueden declarar punteros a constructores por que no se puede obtener la dirección de memoria de este. ▪ Los constructores no pueden declararse virtuales por que al momento de crear al objeto se debe saber exactamente la forma de construcción. ▪ Los constructores no declarar valor de retorno. ▪ Los constructores no pueden ser heredados. ▪ Pueden ser llamados por los constructores de las sub clases. ▪ Una clase puede tener más de un constructor, a esto se le llama sobrecarga. ▪ Los constructores no pueden ser declarados como friend de ninguna clase. ▪ Los constructores pueden incluir iniciadores. ▪ Los constructores pueden tener argumentos por defecto. ▪ Los constructores no admiten su propia clase como argumento. ▪ Los constructores pueden admitir referencias a su propia clase. Laboratorio de Programación II Página 61 Mgter. Ángel Montesinos Sesión N° 03 4. DESTRUCTORES Al igual que los constructores los destructores son métodos especiales cuya función es liberar los recursos ocupados por el objeto al momento de ser creado y de operar. Si el programador no define un constructor explicito, el compilador le proporciona uno, pero se hace imprescindible especialmente si los objetos hacen usode memoria dinámica. A. INVOCACIÓN EXPLÍCITA DE DESTRUCTORES Los destructores son invocados explícitamente de dos formas, la primera de forma indirecta mediante el operador delete y la segunda de forma directa usando el nombre cualificado completo del destructor. B. DECLARACIÓN DE DESTRUCTORES Los destructores se declaran con el mismo nombre de la clase antecedidos por el símbolo virgulilla, esto es para enfatizar su estrecha relación con los constructores ya que este símbolo se usa para indicar el complemento. C. INVOCACIÓN IMPLÍCITA DE DESTRUCTORES Cualquier variable es destruida al salir de su bloque de código de creación, esto se conoce como estar fuera de ámbito; es en estos casos que los destructores son invocados de forma implícita, si se trata d objetos globales esto ocurre al terminar la función main; para el caso de punteros no se llama al destructor al abandonar el bloque de creación, sin embargo los objetos dinámicos a los que apuntan deben ser destruidos de forma explícita llamando al operador delete. D. PROPIEDADES DE LOS DESTRUCTORES Las siguientes: ▪ Los destructores no son heredables al igual que los constructores pueden ser invocados en las clases derivadas. ▪ No se puede obtener la dirección de un destructor por lo cual no existen punteros a destructores. ▪ Solo existe un destructor por clase. La destrucción de objetos se hace de la misma forma para todos los objetos de la clase. ▪ Los destructores no tienen valor de retorno. ▪ Los constructores no aceptan ningún tipo de parámetros ya que la destrucción se hace forma obligatoria. ▪ En un destructor explícito las sentencias del cuerpo se ejecutan antes de destruir a los atributos miembros. ▪ La invocación de los destructores se hace en orden inverso a la invocación de los constructores. ▪ La destrucción de los miembros no estáticos se realiza antes que la de los miembros estáticos. ▪ Los destructores no pueden ser declarados const o volatile. ▪ Los destructores pueden ser invocados desde objetos const y volatile. ▪ Los destructores no pueden ser declarados static ya que supone su invocación sin un objeto. E. DESTRUCTORES Y EL USO DE ABORT Y EXIT Cuando se invoca exit solo las variables globales y objetos globales serán destruidos en su orden normal; cuando se invoca a la función abort() no se invocan destructores ni para los objetos globales. 5. ¿CÓMO SE DECLARA UN OBJETO COMO MIEMBRO DE CLASE? Podemos declarar a un objeto de otra clase como miembro de una clase, para ello solo debemos especificar su clase y luego colocar el nombre del objeto miembro que será atributo de clase. Laboratorio de Programación II Página 62 Mgter. Ángel Montesinos Sesión N° 03 //Código 3.06: otraclase.h //Declaración de una clase cualquiera #ifndef OTRACLASE_H #define OTRACLASE_H #include <iostream> using namespace std; class otraClase { public: otraClase(); otraClase(int, float); void setOtroAtributoInt(int); void setOtroAtributoFloat(float); int getOtroAtributoInt(int); float getOtroAtributoFloat(float); friend ostream& operator <<(ostream&,otraClase&); private: int otroAtributoInt; float otroAtributoFloat; }; #endif Antes de declarar un objeto miembro debemos tener la clase a la cual pertenecerá, esto implica desarrollar la definición de clase y la definición de sus métodos. //Código 3.06: otraclase.cpp //Definición de métodos o funciones miembro de la clase otraClase #include "otraclase.h" #include <iostream> using namespace std; otraClase::otraClase() { otroAtributoInt = 0; otroAtributoFloat = 0; } otraClase::otraClase(int i, float f) { otroAtributoInt = i; otroAtributoFloat = f; } ostream& operator <<(ostream& salida,otraClase& obj) { salida << "otroAtributoInt: " << obj.otroAtributoInt << endl << "otroAtributoFloat: " << obj.otroAtributoFloat << endl; return salida; } La clase construida anteriormente no tiene a objetos como atributos es una clase convencional. Al tener una clase de la cual instanciar objetos construiremos ahora una clase que tenga a objetos de la clase anterior como atributos bajo las tres formas de acceso. //Código 3.07 unaclase.h //Declaración de una clase que contiene objetos como miembros #include "otraclase.h" #ifndef UNACLASE_H Laboratorio de Programación II Página 63 Mgter. Ángel Montesinos Sesión N° 03 #define UNACLASE_H #include <iostream> using namespace std; class unaClase { public: otraClase objetoPublico; unaClase(); unaClase(int, float, otraClase&); friend ostream& operator <<(ostream&,unaClase&); protected: otraClase objetoProtegido; private: int atributoInt; float atributoFloat; otraClase objetoPrivado; }; #endif Debemos tener en cuenta que el nombre de clase debe de ser accesible desde nuestra declaración de clase, por lo tanto debemos incluir el archivo de cabecera que posee la definición de clase del objeto que estamos declarando como miembro. //Código 3.08: unaclase.cpp //Definición de métodos o funciones miembro de la clase unaClase #include "unaclase.h" #include <iostream> using namespace std; unaClase::unaClase() { atributoInt = 0; atributoFloat = 0; } unaClase::unaClase(int i, float f, otraClase &X) : objetoPublico(X), objetoProtegido(X), objetoPrivado(X) { atributoInt = i; atributoFloat = f; } ostream& operator <<(ostream& salida,unaClase& obj) { salida << "atributoInt: " << obj.atributoInt << endl << "atributoFloat: " << obj.atributoFloat << endl << "objetoPublico: " << obj.objetoPublico << endl << "objetoPrivado: " << obj.objetoPrivado << endl << "objetoProtegido: " << obj.objetoProtegido << endl; return salida; } El constructor de clase puede ser por defecto o en caso contario con una lista de inicializadores, de esta forma los objetos miembro podrán ser inicializados correctamente. //Código 3.08: runObjetoMiembro.cpp //Implantacion de clases #include "otraclase.h" #include "unaclase.h" #include <iostream> using namespace std; int main() { Laboratorio de Programación II Página 64 Mgter. Ángel Montesinos Sesión N° 03 otraClase objOtraClase(6,9); unaClase objUnaClase(5,6,objOtraClase); cout << objOtraClase << endl; cout << objUnaClase << endl; system("pause"); return 0; } Salida: otroAtributoInt: 6 otroAtributoFloat: 9 atributoInt: 5 atributoFloat: 6 objetoPublico: otroAtributoInt: 6 otroAtributoFloat: 9 objetoPrivado: otroAtributoInt: 6 otroAtributoFloat: 9 objetoProtegido: otroAtributoInt: 6 otroAtributoFloat: 9 Presione una tecla para continuar . . . Se aprecia en la ejecución del programa que todos los objetos que fueron declarados como atributos fueron inicializados correctamente mediante la lista de inicialización. 6. INICIALIZACIÓN DE MIEMBROS DE CLASE Existen elementos que pueden ser declarados como miembros de una clase para los cuales la inicialización es esencial pero no se puede llevar a cabo este proceso mediante la asignación. Tales como objetos miembro de clases sin constructor por defecto, miembros constates y referencias miembro. //Código 3.09: inicializacionObjetosMiembro.cpp //Demostración de la inicialización de objetos miembro de clase class unaClase { public: unaClase(int arg1, otraClase &objeto ): atributoConstanteInt(arg1), objetoMiembro(objeto), referenciaObjetoMiembro(objetoMiembro) { unAtributoInt = arg1; } void mostrar() { cout << "atributoConstanteInt:" << atributoConstanteInt << endl; cout << "unAtributoInt: " << unAtributoInt << endl; cout << "objetoMiembro: " << objetoMiembro << endl; cout << "referenciaObjetoMiembro: " << referenciaObjetoMiembro << endl; } private: int const atributoConstanteInt; int unAtributoInt; otraClase objetoMiembro; otraClase &referenciaObjetoMiembro; }; int main() { Laboratorio de Programación II Página 65 Mgter. Ángel Montesinos Sesión N° 03 otraClase objOtraClase; objOtraClase.setOtroAtributoInt(32); unaClase objetoUnaClase(3, objOtraClase); objOtraClase.mostrar(); objetoUnaClase.mostrar(); system("pause"); return 0; } ostream& operator << (ostream &salida, otraClase& objeto) { salida << "otroAtributoInt: " << objeto.otroAtributoInt << endl; return salida; } No existe otra forma de inicializar los miembros tratados en el punto anterior y sería un error no poder hacer la inicialización adecuada de los mismos, en la mayoría de los casos para todos los demás tipos el programador dispone de dos formas de hacer dicha inicialización, la primera mediante la asignación directa de valores a los atributos y la segunda mediante el empleo de una lista de inicialización, suele resultar más expresivo y eficiente el segundo recurso. Por ejemplo, en el código anterior se puede observar que el atributo unAtributoInt fue inicializado por la asignación directa del parámetro arg1, en cambio los demás atributos fueron inicializados mediante la lista de inicialización. A. INICIALIZACIÓN DE MIEMBROS CONSTANTES La inicialización de miembros constantes estáticos integrales, es decir enteros, booleanos y caracteres; es posible mediante la utilización de una expresión de inicialización de constantes en la declaración del referido miembro de clase: //Código 3.10: inicializacionMiembrosConstantes.cpp //Demostración de la inicialización de miembro de clase constantes #include <iostream> using namespace std; class otraClase { public: int getOtroAtributoInt() { return otroAtributoInt; } void setOtroAtributoInt(int i) { otroAtributoInt = i; } void mostrar() { cout << "otroAtributoInt: " << otroAtributoInt << endl; cout << "atributoEstaticoConstanteInt: " << atributoEstaticoConstanteInt << endl; } friend ostream& operator << (ostream &salida, otraClase& objeto); private: static const int atributoEstaticoConstanteInt = 5; //static const float atributoconstanteFloat = 3; //error no es integral //static int atributoEstaticoInt = 2; //error no es constante //const int atributoConstanteInt = 1; //error no es estático //static const int otroAtributoEstaticoConstanteInt = // getOtroAtributoInt(); int otroAtributoInt; }; int main() { otraClase objOtraClase; objOtraClase.setOtroAtributoInt(32); Laboratorio de Programación II Página 66 Mgter. Ángel Montesinos Sesión N° 03 objOtraClase.mostrar(); system("pause"); return 0; } ostream& operator << (ostream &salida, otraClase& objeto) { salida << "otroAtributoInt: " << objeto.otroAtributoInt << endl; return salida; } Otra forma alternativa de poder asignar valores a constates es crer una enumeración con enum de constates simbólica dentro de la declaración de la clase: //Código 3.11: inicializacionMiembrosConstantesimbolicas.cpp //Demostración de inicialización de miembro de clase constantes con enum #include <iostream> using namespace std; class otraClase { public: int getOtroAtributoInt() { return otroAtributoInt; } void setOtroAtributoInt(int i) { otroAtributoInt = i; } void mostrar() { cout << "otroAtributoInt: " << otroAtributoInt << endl; cout << "atributoEstaticoConstanteInt: " << atributoEstaticoConstanteInt << endl; cout << "atributoconstanteFloat: " << atributoconstanteFloat << endl; cout << "atributoEstaticoInt: " << atributoEstaticoInt << endl; cout << "atributoConstanteInt: " << atributoConstanteInt << endl; cout << "otroAtributoEstaticoConstanteInt: " << otroAtributoEstaticoConstanteInt << endl; } friend ostream& operator << (ostream &salida, otraClase& objeto); private: enum{atributoEstaticoConstanteInt = 5,atributoconstanteFloat = 2, atributoEstaticoInt = 6,atributoConstanteInt = 9, otroAtributoEstaticoConstanteInt =12}; //static const int atributoEstaticoConstanteInt = 5; //static const float atributoconstanteFloat = 2; //error no es integral //static int atributoEstaticoInt = 6; //error no es constante //const int atributoConstanteInt = 9; //error no es estático //static const int otroAtributoEstaticoConstanteInt int otroAtributoInt; }; int main() { otraClase objOtraClase; objOtraClase.setOtroAtributoInt(32); objOtraClase.mostrar(); system("pause"); return 0; } ostream& operator << (ostream &salida, otraClase& objeto) { salida << "otroAtributoInt: " << objeto.otroAtributoInt << endl; Laboratorio de Programación II Página 67 Mgter. Ángel Montesinos Sesión N° 03 return salida; } Si utilizamos esta alternativa no estaremos tentados a hacer inicializaciones dentro de la clase. 7. RESUMEN Los punteros a objetos almacenan la dirección del objeto a cual apuntan, pero este mecanismo puede ser empleado de una manera similar con un recurso llamado referencia, el cual maneja la dirección del objeto o sus miembros pero por el contario actúa como un alias del recurso al cual hace referencia; durante la construcción de los métodos debemos muchas veces hacer mención al objeto que está manipulando los recursos y no existe una forma clara de hacerlo porque eso lo hará el mismo objeto instanciado, el puntero implícito this se refiere al objeto que está ejecutando el método en ese momento; las autoreferencias permuten encadenar la ejecución de métodos por un mismo objetos, de esta forma es más potente el envío de mensajes. los constructores son los recursos(métodos) encargados de hacer que un objeto aparezca de forma adecuada en un programa, sin ellos los objetos pueden ser construidos de forma errónea, los compiladores manejan constructores por defecto. Los destructores son el método inverso al constructor, mientras los constructores crean adecuadamente a un objeto un destructor elimina adecuadamente a un objeto y recupera de forma adecuada los recursos asignados a dicho objeto, como por ejemplo la memoria, los constructores y destructores tienen el mismo nombre de la clase, ambos se invocan implícitamente, los primeros al ser creado un objeto y los segundos al dejar de tener sentido el objeto en el contexto donde funcionaba. La diferencia entre un constructor y un destructor es el carácter virgulilla(~), que significa la negación IV EXPERIENCIAS DE PRACTICA 1. Constructores y destructores: Crear los respectivos métodos constructores y destructores para cada clase modelando adecuadamente la inicialización de cada objeto de clase y su desaparición en la operación del programa. 2. Objetos como atributosde clase: Agregar a objetos como atributos de clase modelando adecuadamente los constructores y destructores así como los métodos que estarán involucrados en su operación y procesamiento. V EJERCICIOS 1. Elaborar un mapa de los mensajes de los métodos. 2. Agregar un menú de opciones al programa. VI CUESTIONARIO 1. ¿Qué es un puntero? 2. ¿Qué es una referencia? 3. ¿Qué es una autoreferencia? 4. ¿Cómo se usan las referencias a objetos? 5. ¿Por qué tenemos que usar referencias? 6. ¿Por qué tenemos que usar auto referencias?7. ¿Qué es el puntero implícito this? 8. ¿Cómo se usa el puntero implícito this? 9. ¿Por qué tenemos que usar el puntero implícito this? 10. ¿Cuáles son los tipos de clases de almacenamiento? 11. ¿Cuál es la forma como se representa una clase en UML? 12. ¿Cómo se representa los miembros públicos en un diagrama de clases? 13. ¿Cómo se representa los miembros privados en un diagrama de clases? Laboratorio de Programación II Página 68 Mgter. Ángel Montesinos Sesión N° 03 14. ¿Cómo se representa los miembros protegidos en un diagrama de clases? 15. ¿Cómo se representa una relación binaria en un diagrama de clases? 16. ¿Cómo se representa una relación reflexiva en un diagrama de clases? 17. ¿Cómo se representa una relación n-aria en un diagrama de clases? 18. ¿Cómo se representa una relación de agregación en un diagrama de clases? 19. ¿Cómo se representa una relación de composición en un diagrama de clases? 20. ¿Cómo se representa una relación de dependencia en un diagrama de clases? 21. ¿Cómo se representa una relación de herencia en un diagrama de clases? VII BIBLIOGRAFIA Y REFERENCIAS • Deitel, Paul J., Deitel, Harvey M., "Cómo Programar en C++", 6ta Edición, Ed. Pearson Educación, México 2009. • Stroustrup, Bjarne, "El Lenguaje de Programación C++", 3ra Edición, Adisson Pearson Educación S.A., Madrid 2002. • Eckel, Bruce, "Thinking in C++", 2da Edición, Prentice Hall, 2000.
Compartir