lunes, 9 de agosto de 2010

Ultimos Programas

Programas

Estos son los ultimos programas que se hicieron en el curso de verano de PROGRAMACION 1, espero y sean de su agrado.



Para tenerlos en carpeta junto con el programa para ver como funcionan, su estructura y diseño , ingrese al siguiente link: http://rapidshare.com/files/412025742/TC4.zip



Si quieren ver los programas uno por uno y sin necesidad de la carpeta aqui tienen las siguientes imagenes de los mismo programas que vienen en la carpeta.



Los programas son:














miércoles, 4 de agosto de 2010

Unidad VII Archivos

Unidad VII

Archivos


7.1 Clases de E/S clase base abstracta


Se quiere la clase base para presentar sólo una interfaz para sus clases derivadas. Esto es, se puede querer que nadie pueda crear un objeto de la clase base y que ésta sirva únicamente para hacer un upcast hacia ella, y poder tener una interfaz. Se consigue haciendo a la clase abstract (abstracta), poniendo como mínimo una función virtual pura. Si alguien intenta hacer un objeto de una clase abstracta, el compilador lo impide. Esta es una utilidad que fuerza a un diseño en concreto.


Cuando se hereda una clase abstracta, hay que implementar todas las funciones virtuales, o la clase que hereda se convierte en una nueva clase abstracta. Crear una función virtual pura permite poner una función miembro en una interfaz sin forzar a proveer un cuerpo con código sin significado para esa función miembro. Al mismo tiempo, una función virtual fuerza a las clases que la hereden a que implemente una definición para ellas.


La clase base abstracta Stream es compatible con bytes de lectura y escritura. Stream tiene compatibilidad asincrónica. Sus implementaciones predeterminadas definen lecturas y escrituras asincrónicas según sus correspondientes métodos asincrónicos, y viceversa.Todas las clases que representan secuencias se derivan de la clase Stream. La clase Stream y sus clases derivadas proporcionan una visión genérica de los orígenes de datos y los repositorios, aislando al programador de los detalles específicos del sistema operativo y sus dispositivos subyacentes.

Las secuencias comprenden estas operaciones fundamentales:


En las secuencias se puede leer: La lectura es la transferencia de datos desde una secuencia a una estructura de datos, como, por ejemplo, una matriz de bytes.


En las secuencias se puede escribir: La escritura consiste en la transferencia de información desde un origen de datos a una secuencia.


Las secuencias pueden admitir operaciones de búsqueda: Las operaciones de búsqueda consisten en la Mconsulta y modificación de la posición actual en una secuencia.


7.2 Realizar entrada y salida de texto


En C un archivo puede ser cualquier cosa, desde un archivo de disco a un terminal o una impresora. Se asocia una secuencia con un archivo específico realizando una operación de apertura, una vez que está abierto, la información puede ser intercambiada entre éste y el programa. El puntero a un archivo es el hilo que unifica el sistema de E/S con buffer. Un puntero a un archivo es un puntero a una información que define varias cosas sobre él, incluyendo el nombre, el estado y la posición actual del archivo. En esencia, el puntero a un archivo identifica un archivo en disco específico y utiliza la secuencia asociada para dirigir el funcionamiento de las funciones de E/S con buffer. Para obtener una variable de tipo puntero a archivo se debe utilizar una sentencia como la siguiente:


FILE *punt;


La función fopen() abre una secuencia para que pueda ser utilizada y le asocia a un archivo. Su prototipo es: FILE *fopen(const char *nombre_archivo, const char *modo); Donde nombre_archivo es un puntero a una cadena de caracteres que representan un nombre válido del archivo y puede incluir una especificación de directorio. La cadena que apunta modo determina cómo se abre el archivo.


Los modos son los siguientes:

r: Abre un archivo de texto para lectura.

w: Crea un archivo de texto par escritura

a: Abre un archivo de texto para añadir

r+: Abre un archivo de texto para lectura/escritura

w+: Crea un archivo de texto para lectura/escritura

a+: Añade o crea un archivo de texto para lectura/escritura


La función fclose() cierra una secuencia que fue abierta mediante una llamada a fopen(). Escribe toda la información que todavía se encuentre en el buffer del disco y realiza un cierre formal del archivo a nivel del sistema operativo. También libera el bloque de control de archivo asociado con la secuencia, dejándolo libre para su reutilización. A veces es necesario cerrar algún archivo para poder abrir otro, debido a la existencia de un límite del sistema operativo en cuanto al número de archivos abiertos.

Su prototipo es:


int fclose(FILE *fp);


La función putc() escribe caracteres en un archivo que haya sido abierto previamente para operaciones de escritura, utilizando la función fopen().

Su prototipo es:


int putc(int car, FILE *pf);


La función getc() escribe caracteres en un archivo que haya sido abierto, en modo lectura, mediante fopen().

Su prototipo es:


int getc(FILE *pf);


La función fputs() escribe la cadena en la secuencia especificada.

Su prototipo es: fputs() escribe la cadena en la secuencia especificada. Su prototipo es: int fputs(const char *cad, FILE *pf);


La función fgets() lee una cadena de la secuencia especificada hasta que se lee un carácter de salto de línea o hasta que se han leído longitud-1 caracteres.


La función rewind() inicia el indicador de posición al principio del archivo indicado por su argumento. Su prototipo es: rewind() inicia el indicador de posición al principio del archivo indicado por su argumento. Su prototipo es:


void rewind(FILE *pf);


Existen otras muchas funciones en la biblioteca estándar de C como pueden ser:
remove(): Borra el archivo especificado.

fflush(): Vacía el contenido de una secuencia de salida.

fread(): Lee tipos de datos que ocupan más de un byte. Permiten la lectura de bloques de cualquier tipo de datos.

fwrite(): Escribe tipos de datos que ocupan más de un byte. Permiten la escritura de bloques de cualquier tipo de datos.

fprintf(): Hace las funciones de printf() sobre un fichero.

fscanf(): Hace las funciones de scanf() sobre un fichero.

feof(): Detecta el final de un fichero.

ferror(): Detecta un error en la lectura/escritura de un fichero.

fclose(): cierra una secuencia que fue abierta mediante una llamada a fopen().

putc(): escribe caracteres en un archivo que haya sido abierto previamente para operaciones de escritura, utilizando la función fopen().

getc(): escribe caracteres en un archivo que haya sido abierto, en modo lectura, mediante fopen(). Su prototipo es:fputs(): escribe la cadena en la secuencia especificada. Su prototipo es: int fputs(const char *cad, FILE *pf);fgets(): lee una cadena de la secuencia especificada hasta que se lee un carácter de salto de línea o hasta que se han leído longitud-1 caracteres. Su prototipo es: fgets() lee una cadena de la secuencia especificada hasta que se lee un carácter de salto de línea o hasta que se han leído longitud-1 caracteres. Su prototipo es:int fgets(char *cad, FILE *pf);


EN C++:Cómo podemos trabajar con un stream simultáneamente en entrada y salida. Para eso usaremos la clase fstream, que al ser derivada de ifstream y ofstream, dispone de todas las funciones necesarias para realizar cualquier operación de entrada o salida.Hay que tener la precaución de usar la opción ios::trunc de modo que el fichero sea creado si no existe previamente.


7.3 Leer y escribir archivos


Leer archivos: Ifstream


Proporciona una interfaz para leer datos de archivos como flujos de entrada. Los objetos de esta clase tratan de mantener internamente un puntero a un objeto filebuf que se pueden obtener llamando a rdbuf miembros.


El archivo que se asocia con la corriente puede ser especificado como un parámetro en el constructor o llamando a los miembros abierta.


Después de todas las operaciones necesarias en un archivo se han realizado, puede ser cerrado (o disociada) llamando a cerrar miembros. Una vez cerrado, el mismo objeto de secuencia de archivo puede ser usado para abrir otro archivo.


El is_open función miembro puede ser usado para determinar si el objeto de secuencia está asociada con un archivo.

Escribir archivos: Ofstream


Proporciona una interfaz para escribir datos en archivos como los flujos de salida. Los objetos de esta clase de mantener internamente un puntero a un objeto filebuf que se pueden obtener llamando a rdbuf miembros.
El archivo que se asocia con la corriente puede ser especificado como un parámetro en el constructor o llamando a los miembros abierta.


Después de todas las operaciones necesarias en un archivo se han realizado, puede ser cerrado (o disociada) llamando a cerrar miembros. Una vez cerrado, el mismo objeto de secuencia de archivo puede ser usado para abrir otro archivo.


El is_open función miembro puede ser usado para determinar si el objeto de secuencia está asociada con un archivo.


7.4 Realizar entrada y salida binaria


Muchos sistemas operativos distinguen entre ficheros de texto y ficheros binarios. Por ejemplo, en MS-DOS, los ficheros de texto sólo permiten almacenar caracteres.En otros sistemas no existe tal distinción, todos los ficheros son binarios. En esencia esto es más correcto, puesto que un fichero de texto es un fichero binario con un rango limitado para los valores que puede almacenar.


En general, usaremos ficheros de texto para almacenar información que pueda o deba ser manipulada con un editor de texto. Un ejemplo es un fichero fuente C++. Los ficheros binarios son más útiles para guardar información cuyos valores no estén limitados. Por ejemplo, para almacenar imágenes, o bases de datos. Un fichero binario permite almacenar estructuras completas, en las que se mezclen datos de cadenas con datos numéricos.


En realidad no hay nada que nos impida almacenar cualquier valor en un fichero de texto, el problema surge cuando se almacena el valor que el sistema operativo usa para marcar el fin de fichero en un archivo de texto. En MS-DOS ese valor es 0x1A. Si abrimos un fichero en modo de texto que contenga un dato con ese valor, no nos será posible leer ningún dato a partir de esa posición. Si lo abrimos en modo binario, ese problema no existirá.


Algunos de los ejemplo anteriores acontoinuación se muestran en binario:


#include

#include

struct tipoRegistro

{

char nombre[32];

int edad;

float altura;

};
int main()

{

tipoRegistro pepe;

tipoRegistro pepe2;

ofstream fsalida("prueba.dat",

ios::out ios::binary);

strcpy(pepe.nombre, "Jose Luis");

pepe.edad = 32;

pepe.altura = 1.78;

fsalida.write(reinterpret_cast(&pepe),

sizeof(tipoRegistro));

fsalida.close();
ifstream fentrada("prueba.dat",

ios::in ios::binary);

fentrada.read(reinterpret_cast(&pepe2),

sizeof(tipoRegistro));


}



Referencias:






Unidad VI Polimorfismo

Unidad VI

Polimorfismo



6.1 Concepto de polimorfismo.

En programación orientada a objetos se denomina polimorfismo a la capacidad del código de un programa para ser utilizado con diferentes tipos de datos u objetos. También se puede aplicar a la propiedad que poseen algunas operaciones de tener un comportamiento diferente dependiendo del objeto (o tipo de dato) sobre el que se aplican.



El concepto de polimorfismo se puede aplicar tanto a funciones como a tipos de datos. Así nacen los conceptos de funciones polimórficas y tipos polimórficos. Las primeras son aquellas funciones que pueden evaluarse o ser aplicadas a diferentes tipos de datos de forma indistinta; los tipos polimórficos, por su parte, son aquellos tipos de datos que contienen al menos un elemento cuyo tipo no está especificado.


Se puede clasificar el polimorfismo en dos grandes clases:




  • Polimorfismo dinámico: (o polimorfismo ad hoc) es aquél en el que el código no incluye ningún tipo de especificación sobre el tipo de datos sobre el que se trabaja. Así, puede ser utilizado a todo tipo de datos compatible.



  • Polimorfismo estático: (o polimorfismo paramétrico) es aquél en el que los tipos a los que se aplica el polimorfismo deben ser explicitados y declarados uno por uno antes de poder ser utilizados. El polimorfismo dinámico unido a la herencia es lo que en ocasiones se conoce como programación genérica.


6.2 Clase base abstracta.


En C++ es posible definir clases abstractas. Una clase abstracta, o clase base abstracta (ABC), es una que está diseñada sólo como clase padre de las cuales se deben derivar clases hijas. Una clase abstracta se usa para representar aquellas entidades o métodos que después se implementarán en las clases derivadas, pero la clase abstracta en sí no contiene ninguna implementación solamente representa los métodos que se deben implementar. Por ello, no es posible instanciar una clase abstracta, pero sí una clase concreta que implemente los métodos definidos en ella.



Las clases abstractas son útiles para definir interfaces, es decir, un conjunto de métodos que definen el comportamiento de un módulo determinado. Estas definiciones pueden utilizarse sin tener en cuenta la implementación que se hará de ellos.


Ejemplo:


class Abstracta


{


public:virtual


int metodo() = 0;


};



6.3 Subprogramas virtuales.


Las funciones virtuales permiten que clases derivadas de una misma base (clases hermanas) puedan tener diferentes versiones de un método. Se utiliza la palabra-clave virtual para avisar al compilador que un método será polimórfico y que en las clases derivadas existen distintas definiciones del mismo.



Para declarar que un método de una clase base es virtual, su prototipo se declara como siempre, pero anteponiendo la palabra-clave virtual, que indica al compilador algo así como: "Será definido más tarde en una clase derivada".


Ejemplo:


Sintaxis: virtual void dibujar();


Una función virtual o método virtual es una función cuyo comportamiento, al ser declarado "virtual", es determinado por la definición de una función con la misma cabecera en alguna de sus subclases. Este concepto es una parte muy importante del polimorfismo en la POO.



6.4 Destructores virtuales.



Como cualquier otra función miembro, los destructores pueden ser declarados virtuales. El destructor de una clase derivada de otra cuyo destructor es virtual, también es virtual.



La existencia de un destructor virtual permite que un objeto de una subclase pueda ser correctamente destruido por un puntero a su clase-base.


Ejemplo:


class B


{


// Superclase (polimórfica) ...


virtual ~B(); // Destructor virtual


};


class D : public B

{

// Subclase (deriva de B) ...


~D(); // destructor también virtual


};

void func()

{

B* ptr = new D; // puntero a superclase asignado a objeto de subclase

delete ptr; // Ok: delete es necesario siempre que se usa new

}

En el ejemplo anterior el mecanismo de llamada de las funciones virtuales permite que el operador delete invoque al destructor correcto, es decir, al destructor ~D de la subclase, aunque se invoque mediante el puntero ptr a la superclase B*. Si el destructor no hubiese sido virtual no se hubiese invocado el destructor derivado ~D, sino el de la superclase ~B, dando lugar a que los miembros privativos de la subclase no hubiesen sido desasignados. Tendríamos aquí un caso típico de "misteriosas" pérdidas de memoria, tan frecuentes en los programas C++ como difíciles de depurar.

Referencias:

martes, 3 de agosto de 2010

Unidad V Herencia

Unidad V
Herencia


5.1 Importancia de la herencia en la POO


La herencia es la propiedad que permite a los objetos ser construidos a partir de otros objetos. Dicho de otro modo, la capacidad de un objeto para utilizar las estructuras de datos y los métodos previstos en antepasados o ascendientes. El objetivo final es la reutilización, es decir, reutilizar código anteriormente ya desarrollado.


La herencia supone una clase base y una jerarquía de clases que contienen las clases derivadas de la clase base.


Una clase hereda sus características (datos y funciones) de otra clase.


La herencia es un mecanismo potente para tratar con la evolución natural de un sistema y con modificación incremental.


5.2 Jerarquía de herencia


Existen dos tipos de herencia: simple y múltiple.


5.2.1 Conceptos de herencia simple y múltiple.

La herencia simple permite que una clase herede las propiedades de su superclase en una cadena jerárquica. En esta jerarquía cada clase tiene como máximo una solo superclase.

La herencia múltiple es la propiedad de una clase de poder tener más de un ascendiente inmediato, o lo que es igual, adquirir datos y métodos de más de una clase.

5.2.2 Principios generales de diseño de jerarquías

Incluso las jerarquías de clases bien diseñadas necesitan evolucionar con el tiempo. Las opciones iniciales que elija en el momento de diseñar una jerarquía de clases pueden simplificar su trabajo posteriormente.



En la siguiente lista se incluyen sugerencias para simplificar la extensión de las jerarquías de clases:


• Las jerarquías se definen desde lo general a lo específico. Defina las clases en cada nivel de una jerarquía de herencia de la forma más genérica posible. Las clases derivadas pueden heredar, reutilizar y extender métodos de clases base. Por ejemplo, suponga que está diseñando una jerarquía de clases que modela el hardware del equipo. Al comenzar a modelar los dispositivos de salida, podría definir clases denominadas Display, Printer y File. Después podría definir las clases que implementan los métodos definidos en las clases base. Por ejemplo, la clase LCD Display puede haber derivado de Display e implementar un método denominado Enter Power Save Mode.



• Defina los tipos de datos y el almacenamiento con generosidad a fin de evitar cambios difíciles posteriormente. Por ejemplo, podría considerar el uso de una variable de tipo Long aunque los datos actuales sólo requieran una variable estándar Integer.



• Exponga sólo los elementos que las clases derivadas necesiten. Los campos y métodos Private reducen los conflictos de denominación y protegen a otros usuarios del uso de elementos que pueden necesitar cambios posteriormente.



• Los miembros que sólo sean necesarios para las clases derivadas deben marcarse como Protected. Esto garantiza que sólo las clases derivadas dependen de estos miembros y facilita la actualización de estos miembros durante el desarrollo.



• Asegúrese de que los métodos de clase base no dependen de miembros Overridable cuya funcionalidad pueden cambiar las clases herederas. Existen dos tipos de jerarquizar: La primera consiste en derivar una clase de otra, es el caso mas habitual y se llama “Herencia”. La otra consiste en encapsular un objeto como miembro de otro, a esta se le llama “Encapsulamiento”.



La unica regla que tenemos que tener en mente es: Si un objeto se relaciona con otro de la forma “es un” hay que usar la herencia publica. Si por el contrario la relacion se describe mejor de la forma “tiene un” hay que usar el encapsulamiento.



Una forma sencilla de ver la diferencia entre los dos tipos es con este ejemplo:



• La clase C Mercedes? “es un” tipo de la clase C Car?


• La clase C Mercedes “tiene un” tipo de case C Volante?



5.2.3 Especificadores de acceso a jerarquía de clases


C++ utiliza especificadores de acceso para permitir controlar a una clase el acceso a las variables de datos de esa clase. Los especificadores de acceso permiten acceder a algunos miembros de la clase y restringir el acceso a otros. Hay tres especificadores de acceso en C++: public, private y protected. Cuando usted declara público ( public) un miembro de una clase, usted permite el acceso a tal miembro desde dentro y fuera de la clase. Los miembros de datos que son declarados protegidos ( protected ) son únicamente accesibles por funciones miembro de la clase, pero no se pueden acceder a ellos desde otras clases. Cuando un miembro de una clase es declarado privado ( private ) es ináccesible no sólo desde otras clases y otras partes del programa, sino también desde sus clases derivadas. Las clases derivadas se explicara posteriormente.


Miremos el siguiente programa de ejemplo. Se compone de tres partes: la primera una declaración de una clase llamada Empleado:
class Empleado

{

private:

char* m_nombre;

char* m_departamento;

char* m_posicion;

long m_salario;

public:

void ImprimirInfo();

void SetNombre( char* nombre ) { m_nombre = nombre }

void SetDepartamento( char * departamento) { m_departamento = departamento }

void SetPosicion ( char* posicion ) { m_posicion = posicion }

void SetSalario ( long salario ) { m_salario = salario }

const char* GetNombre( ){ return m_nombre }

const char* GetDepartamento( ){ return m_departamento }

const char* GetPosicion( ){ return m_posicion }

const char* GetSalario( ){ return m_salario }

};


Las funciones SetNombre, SetDepartamento, setPosicion, setSalario, GetNombre, GetDepartamento, GetPosicion y GetSalario se denominan funciones intercaladas, que son funciones que se declaran en una sola línea.


Las variables de miembro son declaradas privadas para que funciones de miembro de otras funciones no tengan acceso a ellas sino a travez de la correspondiente funcion Get o Set.


Las funciones de miembro si son declaradas públicas de tal modo que se pueda acceder a ellas desde otras funciones.


5.3 Definición de una clase base

Cuando pensamos en una clase como un tipo, asumimos que los programas crearán objetos de ese tipo. Sin embargo, hay casos en que es útil definir clases para las cuales no se desea instanciar objetos. Tales clases son llamadas clases abstractas. Debido a que normalmente son utilizadas como base en jerarquías de clases, nos referiremos a ellas como clases base abstractas.


Las clases abstractas no sirven para instanciar objetos porque están incompletas, siendo sus clases derivadas las que deberán definir las partes faltantes.



El propósito de una clase abstracta es proveer una clase base apropiada desde la cual otras clases hereden.



Las clases desde las cuales se pueden instanciar objetos se llaman clases concretas. Tales clases proveen implementaciones de cada método o propiedad que definen.



Las clases abstractas normalmente contienen uno o más métodos o propiedades abstractas, las cuales no proveen implementación. Las clases derivadas deben reemplazar los métodos abstractos heredados para permitir la instanciación de objetos.



Para definir una clase abstracta se utiliza la palabra clave abstract (que también sirve para definir métodos y propiedades abstractos).



Ejemplo :
// Clase abstracta con métodos abstractos;
abstract class Figura{
protected int x, y ;
public abstract double daPerímetro( ) ; // Declaración de un método abstracto.
public abstract double daArea( ) ; // Declaración de un método abstracto.
}



5.4 Definición de una clase derivada

La clase derivada se crea a partir de otra ya existente, denominada clase base.

La declaración de derivación de clases debe incluir el nombre de la clase base de la que se deriva y el especificador de acceso que indica el tipo de herencia (publica, privada y protegida). La primera línea de cada declaración debe incluir el formato siguiente:

class nombre_clase : tipo_herencia nombre_clase_base
{
// tipos de miembros
};

5.4.1 Constructores y destructores de una clase derivada


Una clase derivada es una especialización de una clase base. En consecuencia el constructor de la clase base debe ser llamado para crear un objeto de la clase base antes de que el constructor de la clase derivada realice su tarea.

Reglas

1. Los constructores de las clases base se invocan antes del constructor de la clase derivada; los constructores de la clase base se invocan en la secuencia en que están especificados.
2. Si una clase base es, a su vez, una clase derivada, sus constructores se invocan también en secuencia: constructor base, constructor derivada.
3. Los constructores no se heredan, aunque los constructores por defecto y de copia, se generan si se requiere.

Sintaxis del constructor de una clase derivada:

nombre_clase_derivada:: nombre_clase_derivada(parámetros):nombre_clase_base(parámetros), listas_inicializacion _miembrosdato
{
// Cuerpo constructor de la clase derivada

};


El constructor de la clase derivada tiene que realizar dos tareas:
1. Inicializar el objeto base
2. Inicializar todos los miembros dato

La clase derivada tiene un constructor inicializador, que llama a uno o más constructores de la clase base. El inicializador aparece inmediatamente después de los parámetros del constructor de la clase derivada y está precedido por dos puntos (:).

Los destructores son mucho mas fáciles de tratar que los constructores. Los destructores no se heredan, aunque se genera un destructor por defecto si se requiere. Un destructor normalmente sólo se utiliza cuando un constructor correspondiente ha asignado espacio de memoria que debe ser liberado. Los destructores se manejan como los constructores excepto que todo se hace en orden inverso. Esto significa que el destructor de la ultima clase derivada se ejecuta primero.

5.4.2 Conversión implícita de objetos de clase derivada a objetos de clase base

La programación orientada a objetos extiende los tipos abstractos de datos permitiendo relaciones tipo-subtipo. Esto es alcanzado a través de un mecanismo denominado herencia. Más que reimplementar características compartidas, una clase puede heredar datos y funciones miembros de otras clases. En C++, este mecanismo es implementado a través de la derivación de clases.

Especificación de derivación

// clases que sirven como clases base

class Animal{...};

class EnExtincion{...};

class Carnivoro{...};

class Herbivoro{...};

// Derivación simple

class Oso:public Animal { ...};

// Derivaciones múltiples

class Gato : public Animal, Carnivoro {...};

class Panda : private EnExtincion, public Oso, private Herbivoro {...};

Si se omite un atributo de público,privado o protegido a la clase base, esta es manipulada como privada. En el caso de la clase gato, Carnivoro es una clase base privada.

La sintaxis para definir clases bases es igual a definir clases ordinarias, con las siguientes dos excepciones:

  • Miembros que se quiere sean heredados por clases derivadas, pero no públicos son declarados miembros protegidos.

  • Funciones miembro cuya implementación depende de detalles de representación de subsecuentes derivaciones y que son desconocidas al tiempo del diseño de la clase base son declaradas como funciones virtuales.


El acceso desde clases derivadas a miembros heredados es como si fueran miembros propios (depende del tipo de herencia realizada). Tambien puede usarse el class scope operator es decir, para acceder al miembro A de la clase ClassA desde el objeto Obj de la clase ClassB sería Obj.ClassA::A o bien Obj.A.

Clases bases públicas y derivadas


Los miembros heredados de una clase base pública mantienen su nivel de acceso dentro de la clase derivada. En general, en una jerarquía de derivación pública, cada clase derivada subsecuentemente tiene acceso combinado a miembros públicos y protegidos de las clases bases previas en una rama. Los miembros públicos y protegidos heredados a través de una derivación protegida, se vuelen miembros protegidos de la clase derivada. Los miembros públicos y protegidos heredados a traves de una derivación privada se vuelven miembros privados de la clase derivada. Esto lleva a:


  • Los miembros públicos de una clase base no pueden ser accedidos a través de un objeto de una clase derivada.

  • Los miembros públicos y protegidos de la clase base ya no seran más visibles en subsecuentes derivaciones.


Conversiones estándar bajo derivación


Existen 4 conversiones predefinidas que son aplicables entre una clase derivada y su clase base pública:


  • Un objeto de la clase derivada se convierte en forma implícita en un objeto de la clase base pública.

  • Una referencia a una clase derivada se convierte implícitamente en una referencia a la clase base pública.

  • Un puntero a la clase derivada se convertirá implícitamente en un puntero a la clase base.

  • Un puntero a un miembro de una clase base se convertirá en forma implícita en un puntero a miembro de la clase derivada.


5.5 Herencia múltiple

Es un tipo de herencia en la que una clase hereda el estado (estructura) y el comportamiento de más de una clase base.

La herencia múltiple puede simplificar los programas y proporcionar soluciones para resolver problemas difíciles.

La herencia múltiple plantea diferentes problemas tales como la ambigüedad por le uso de nombres idénticos en diferentes clases base, y la dominación o preponderancia de funciones o datos.


Referencias:

Unidad IV Clases y Objetos

UNIDAD IV
Clases y Objetos

4.1 Definición de una clase

Una clase es un tipo definido por el usuario. Las clases son el bloque de construcción fundamental de los programas orientados a objetos.

Una clase contiene la especificación de los datos que describen un objeto junto con la descripción de las acciones que un objeto conoce cómo ha de ejecutarse.

Una clase incluye también todos los datos necesarios para describir los objetos creados a partir de la clase. Estos datos se conocen como atributos o variables.

La definición de una clase significa que se debe dar a la misma un nombre, darle nombre a los elementos que almacenan sus datos y describir las funciones que realizarán las acciones consideradas en los objetos. No reserva espacio en memoria.

Las definiciones o especificaciones no son código de programa ejecutable. Se utilizan para asignar almacenamiento a los valores de los atributos usados por el programa y reconocer las funciones que utilizará el programa. Normalmente se sitúan en archivos diferentes de los archivos de código ejecutables, utilizando un archivo por cada clase.

Formato:
class nombre_clase
{
listas_de_miembros
};

Donde:
nombre_clase = Definido por el usuario que identifica a la clase (identificadores válidos).
listas_de_miembros = Funciones y datos miembros de la clase.

Ejemplo:
Class Punto
{
public :
int Leerx();
void Fijarx(int);
private:
int x;
int y;
};

Las palabras reservadas public y prívate se llaman especificadores de acceso.

4.2 Declaración de clases

Una declaración de una clase consta de una palabra reservada class y el nombre de la clase. Una declaración de la clase se utiliza cuando el compilador necesita conocer una determinada clase definida totalmente en alguna parte del programa.

Ejemplo:
class Punto;

4.3 Miembros de una clase.
La mayoría de los miembros (métodos y propiedades) descritos hasta ahora en este capítulo son de un tipo denominado miembros de instancias. Por cada miembro de instancia, existe una copia exclusiva de dicho miembro en cada instancia de la clase. Por ejemplo, la variable de miembro email de la clase Sample tiene un miembro de instancia, porque cada persona tiene una dirección de correo electrónico diferente.

Otro tipo de miembro es un miembro de clase. Sólo hay una copia de un miembro de clase, que se utiliza para toda la clase. Todas las variables declaradas dentro de una clase, pero fuera de una función, son propiedades de la clase. En el siguiente ejemplo, la clase Person tiene dos propiedades, age y username, de tipo Number y String, respectivamente:
class Person
{
public var age:Number;
public var username:String;
}

Asimismo, todas las funciones declaradas dentro de una clase se consideran un método de la clase. En el ejemplo de la clase Person, puede crear un método denominado getInfo():

class Person

{

public var age:Number;

public var username:String;

public function getInfo():String

{

// Definición del método getInfo()

}

}

Los miembros de clases se declaran con la palabra clave static. Por ejemplo, puede declarar el miembro de clase species con el siguiente código:

class Person

{
public static var species:String = "Homo sapiens";
// ...
}


4.4 Ámbito referente a una clase.

Una clase actúa como cualquier otro tipo de dato con respecto al ámbito. Todos los miembros de una clase se dice que están en el ámbito de esa clase; cualquier miembro de una clase puede referenciar a cualquier otro miembro de la misma clase.


Las funciones miembro de una clase tienen acceso no restringido a los miembros dato de esa clase. El acceso a los miembros dato y funciones de una clase fuera del ámbito de la clase está controlado por el programador. La idea es encapsular la estructura de datos y funcionalidad de una clase, de modo que el acceso a la estructura de datos de la clase desde fuera de las funciones miembro de la clase, sea limitada o innecesaria.


El nombre de la clase tiene que ser único dentro de su ámbito.


4.5 Especificadores de acceso.

Un principio fundamental en programación orientada a objetos es la ocultación de la información que significa que a determinados datos del interior de una clase no se puede acceder por funciones externas a la clase.

Se utilizan tres diferentes especificadores de acceso para controlar el acceso a los miembros de la clase son: public, private, protected.

Se utiliza el siguiente formato general en definiciones de la clase, situando primero las funciones de la clase, situando primero las funciones miembros públicas, seguidas por los miembros protegidos y privado (este orden no es obligatorio).

class nombre_clase {
public:
//miembros públicos
protected:
//miembros protegidos
private:
//miembros privados
};

El especificador public define miembros públicos, que son aquellos a los que se puede acceder por cualquier función. A los miembros que siguen al especificador private sólo se puede acceder por funciones miembro de la misma clase o por funciones y clases amigas. A los miembros que siguen al especificador protected se puede acceder por funciones miembro de la misma clase o clases derivadas de la misma, así como por amigas. Los especificadores pueden aparecer en cualquier orden.

Si se omite el especificador de acceso, el acceso por defecto es privado

4.6 Creación de objetos

Una vez que una clase ha sido definida, un programa puede contener una instancia de clase, denominada objeto de clase.

Formato:
nombre_clase identificador;

Así, la definición de un objeto Punto es:

Punto P;

El operador punto se utiliza con los nombres de las funciones miembro para especificar que son miembros de un objeto.

Se puede asignar un objeto de una clase a otro; por defecto C++ realiza una copia bit a bit de todos los miembros dato. Todos los miembros físicamente contenidos en el área de datos del objeto fuente se copian en el objeto receptor. Por ejemplo, el siguiente código crea un punto (Punto) llamado P2 y lo inicializa con el contenido de P:

Punto P;
//……
Punto P2;
P2 = P;


4.7 Puntero this.

En C++ se define this dentro de un objeto como un puntero al objeto en que está contenido. Se declara implícitamente como:

class_name *this;


y se inicializa para apuntar al objeto para el cual se llama a la función miembro. Este puntero es muy útil cuando se trabaja con punteros y especialmente en listas linkadas cuando se necesita referenciar un puntero al objeto que se está insertando en la lista. La palabra this está disponible para este propósito y puede ser utilizada en cualquier objeto. Realmente la forma apropiada de referenciar a cualquier variable en una lista es a través del uso del puntero predefinido this, escribiendo this -> variable_name, pero el compilador supone que se está usando, y podemos omitir el puntero.


4.8 Constructores y destructores

Constructor

Un constructor es una función miembro de propósito específico que se ejecuta automáticamente cuando se crea un objeto de una clase. Sirve para inicializar los miembros dato de una clase.
Un constructor tiene el mismo nombre que la clase y no devuelve un valor, pero si puede tener cualquier números de parámetros.

Ejemplo.
class Rectangulo
{
private:
int Izdo;
int Superior;
int Dcha;
int Inferior;
public:
Rectangulo(int I, int S, int D, int Inf); //Constructor
};

Constructor por defecto

Es un constructor que no tiene parámetros. Normalmente inicializa los miembros dato asignándoles valores por defecto.

C++ crea automáticamente un constructor por defecto cuando no existen otros constructores. Sin embargo, tal constructor no inicializa los miembros dato de la clase a un valor previsible, de modo que siempre es conveniente crear su propio constructor por defecto, darle la opción de inicializar los miembros dato con valores previsibles.

Constructores alternativos

Un constructor con parámetros se denomina constructor alternativo.

Ejemplo.
Punto P(50,250); //define e inicializa P

Destructor

En una clase se puede definir también una función miembro especial conocida como destructor, que se llama automáticamente siempre que se destruye un objeto de la clase. El nombre del constructor es el mismo que el nombre de la clase, precedida del carácter ~. Al igual que un constructor, un destructor se debe definir sin ningún tipo de retorno; al contrario que un constructor, no puede aceptar parámetros. Solo puede existir un destructor.

Ejemplo.
class Demo
{
private:
int datos;
public:
Demo () {datos = 0;} //constructor
~Demo () {} //destructor
};

El uso mas frecuente de un destructor es liberar memoria que fue asignada por el constructor. Si un destructor no se declara explícitamente C++ crea un vacío automáticamente.
Si un objeto tiene ámbito local, su destructor se llama cuando el control pasa fuera de su bloque de definición. Si un objeto tiene ámbito de archivo, el destructor se llama cuando termina el programa principal. Si un objeto se asignó dinámicamente, el destructor se llama cuando se invoca el operador delete.
Referencias:

lunes, 26 de julio de 2010

Programas Unidad III

Aqui muestro en imagenes los codigos de los programa que realice en esta unidad, vienen con sus especificaciones.
Si desea bajarlos de una carpeta haga click en el siguiente link para descargar los siguientes programas: http://rapidshare.com/files/409224124/TC3.zip



Unidad III Punteros, Arreglos y Referencias

3.1 Creación

Un puntero es una variable que guarda la dirección de memoria de otro objeto. Para declarar una variabe que sea un puntero, a sintaxis es:
tipo *var-puntero
En la declaración se observa que el nombre de la variable puntero, var-puntero, va precedido del modificador *, el cual significa "puntero a"; tipo especifica el tipo del objeto apuntado, puede ser cualquier tipo primitivo o derivado.
El espacio de memoria requerido para un puntero, es el número de bytes necesarios para especificar una dirección máquina, generalmente 4 bytes.
Un puntero iniciado correctamente siempre apunta a un objeto de un tipo particular. Un puntero no iniciado no se sabe a donde apunta.
3.2 Operaciones con Punteros
A las variables de tipo putero, además de los operadores & (direcció), * (indirección), y el operador de asignación, se les puede aplicar los operadores aritméticos + y - (sólo con enteros), los operadores unitarios ++ y --, y los operadores de relación.
Operación de asignación
El lenguaje C permite que un puntero pueda ser asignado a otro puntero.
Operaciones Aritméticas.
A un puntero se le puede sumar o restar un entero. La aritmética de punteros difiere de la aritmética normal en que aquí la unidad equivale a un objeto del tipo del puntero; esto es, sumar 1 implica que el putero pasará a apuntar al siguiente objeto, del tipo puntero, más allá del apuntado actualmente.
Ejemplo:
int x;
int *p,*q;//declara p y q como punteros
p=&x;//p apunta a x
q=&x;//q aputa a x
La operación p+n, siendo n un entero, avanzará el puntero n enteros más allá del actualmente aputado.
Ejemplo:
p=p+3//hace que p avance tres enteros.
Así mismo, la operación p-q, después de la operación p=p+3 antrior, dará como resultado p.
La operación p-n, siendo n un entero, también es válida.
Si p apunta a x=3, p++ hace que p apunte a x=4, y partiendo de esta sotuación, p-- hace que p apunte de nuevo a x=3.
No se puede sumar, multiplicar, dividir o rotar punteros y tampoco se permite sumarles un real.
Los operadores unitarios &,* tienen prioridad mayor que los operadores aritméticos.
Un puntero a cualquier tipo de objeto puede ser convertido al tipo void*, y recibe el nombre de puntero genérico.
3.3 Referencias
Una referencia es un alias de otra variable. Se declara utilizando el operador de referencia (&) que se añade al tipo de la referencia.
Utilización de referencia:
main()
{
int n=75;
int& r=n;
}
Ejecución:
n=75, r=75
3.4 Arreglos unidimensionales, bidimensionales y multidimensionales
Un arreglo unidimensional se caracteriza por tener un solo subídice. Estos arreglos se conocen también por el término de listas.
C++ crea arreglos unidimensionales con el siguiente formato:
tipo nombre [tamaño];
Los arreglos multidimensionales son aquellos que tienen más de una dimensión conocidos tambien por el nombre de tablas o matrices.
Un arreglo de dos dimensiones equivale a una tabla con multiples filas y multiples columnas. Su sintaxis es:
tipo nombre [numero filas][numero columnas]
Ejemplo:
char pantalla[25][80];
Para declarar un arreglo multidimensional es:
tipo nombre [tamaño1][tamaño2][tamañon];
Cadena de caracteres
Una cadena de caracteres se almacea como una matriz unidimensional de elementos de tipo unsigned char o char.
Ejemplo:
char cadena;
Una matriz unidimensional de caracteres puede ser iniciada en el momento de su definición.
Ejemplo:
char cadena()={'a'.'b','c','d'};
Si se crea una matriz de caracteres y se le asigna un número de caracteres menor que su tamaño, el resto de los elementos quedan con el valor 0 si la matriz global o con basura si es local.
3.6 Asignación dinámica de memoria
La asignación dinámica de memoria consiste en asignar la cantidad de memoria necesaria para almacenar un objeto durante la ejecució de un programa, en vez de hacerlo en el momento de la compilación del mismo. Cuando se asigna memoria para un objeto de un tipo cualquiera, se devuelve un puntero a la zona de memoria asignada.
Lo que tiene que hacer el compilador es asignar una cantidad fija de memoria para almacenar la dirección del objeto asignado para el objeto en sí.
Esto implica declarar un puntero a un tipo de datos igual al tipo del objeto que se quiere asignar dinámicamente.
Funciones para asignación dinámica de memoria
La vivlioteca C proporciona una función para asignar memoria dinámicamente (malloc) y otra para liberar el espacio de memoria asignado para un objeto cuando éste ya no sea necesario (free).
Malloc
Permite asignar un bloque de memoria de nbytes consecutivos en memoria para almacear uno o más objetos de un tipo cualquiera.
Esta función devuelve un puntero genérico (void*) que referecia el espacio asignado. Su sintaxis es:
#include (stdlib.h)
void *malloc (size_t nbytes);
Free
Permite liberar un bloque de memoria asignado por las funciones malloc, calloc o realloc. Si el puntero que referecia el bloque de memoria que deseamos liberar es nulo, la función free no hace nada. Su sintaxis es:
#include (stdlib.h)
void free(void *puntero);
Si la memoria liberada por free no ha sido previamente asignada por malloc, calloc o realloc, se pueden producir errores durante la ejecución del programa.
3.7 Uso de clases predefinidas para arreglos

En el lenguaje de programación C una estructura(struct) es lo mismo que una clase, en este caso se explica referente a un struct.

Se puede crear un array de estructuras tal como se crea un array de otros tipos. Los arrays de estructuras son idóneos para almacenar un archivo completo de empleados, un archivo de inventario, o cualquier otro conjunto de datos que se adapte a un formato de estructura. Mientras que los arrays proporcionan un medio práctico de almacenar diversos valores del mismo tipo, los arrays de estructuras le permiten almacenar juntos diversos valores de diferentes tipos, agrupados como estructuras.

Muchos programadores de C utilizan arrays de estructuras como un método para almacenar datos en un archivo de disco. Se pueden introducir y calcular sus datos de disco en arrays de estructuras y a continuación almacenar esas estructuras en memoria. Los arrays de estructura proporcionan también un medio de guardar datos que se leen del disco.

La declaración de un array de estructuras info_libro se puede hacer de un modo similar a cualquier array es decir:
struc info_libro libros [100];

Asigna un array de 100 elementos denominado libros. Para acceder a los miembros de cada uno de los elementos estructura se utiliza una notación de array. Para inicializar el primer elemento de libros, por ejemplo, su código debe hacer referencia a los miembros de libros [0] de la forma siguiente:

strcpy (libros [0].titulo, "C++ a su alcance");

Refencias: