Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Notas POO (2000) PDF
Notas POO (2000) PDF
Notas de clase.
Elaborado por:
Carlos Alberto Fernndez y Fernndez
Instituto de Electrnica y Computacin
Universidad Tecnolgica de la Mixteca.
Programacin Orientada a Objetos con C++
Contenido
Herencia. ............................................................................................................. 81
Introduccin....................................................................................................... 81
Implementacin en C++. ................................................................................... 82
Control de Acceso a miembros. ......................................................................... 84
Control de acceso en herencia........................................................................... 85
Manejo de objetos de la clase base como objetos de una clase derivada y
viceversa. ........................................................................................................... 91
Constructores de clase base............................................................................... 95
Redefinicin de mtodos .................................................................................... 98
Herencia Mltiple. ........................................................................................... 101
Ambigedades. .............................................................................................. 105
Constructores................................................................................................. 108
Funciones virtuales y polimorfismo. ............................................................... 109
Clase abstracta y clase concreta. .................................................................... 112
Polimorfismo.................................................................................................... 113
Destructores virtuales. ..................................................................................... 113
Plantillas de clase.............................................................................................. 128
Caractersticas de C++.
Comentarios en C++.
/* comentario en C */
Flujo de entrada/salida
printf("Nmero: ");
scanf("%d", &num);
printf("El valor ledo es: " %d\n", num);
Funciones en lnea.
Las funciones inline deben usarse slo para funciones chicas que se usen
frecuentemente.
Declaracin:
Ejemplo:
Notas: Las funciones inline tienen conflictos con los prototipos, as que
deben declararse completas sin prototipo en el archivo .h. Adems, si la funcin
hace uso de otra funcin (cosa que puede anular el inline) en donde se expanda la
funcin debe tener los include correspondientes a esas funciones utilizadas.
Declaraciones de variables.
Ejemplo:
#include <iostream.h>
#include <conio.h>
main() {
// int i=0;
clrscr();
// int j=10;
// cout<<j<<'\n';
for (int i=1; i<10; i++){
int j=10;
cout<<i<<" j: "<<j<<'\n';
}
Ejemplo:
float h;
void g(int h) {
float a;
int b;
Las funciones en C++ pueden tener valores por default. Estos valores son
los que toman los parmetros en caso de que en una llamada a la funcin no se
encuentren especificados.
Los valores por omisin deben encontrarse en los parmetros que estn ms
a la derecha. Del mismo modo, en la llamada se deben empezar a omitir los
valores de la extrema derecha.
Ejemplo:
#include <iostream.h>
#include <conio.h>
main () {
cout<<"valor 1: "<<punto()<<'\n';
cout<<"valor 2: "<<punto(1)<<'\n';
cout<<"valor 3: "<<punto(1,3)<<'\n';
getch();
}
if(y!=4)
return y;
if(x!=5)
return x;
return x+y;
}
punto( , 8);
#include <iostream.h>
#include <conio.h>
int b=1;
int f(int);
int h(int x=f(b)); // argumento default f(::b)
void main () {
clrscr();
b=5;
cout<<b<<endl;
{
int b=3;
cout<<b<<endl;
cout<<h(); //h(f(::b))
}
getch();
}
En C todos los pasos de parmetros son por valor, aunque se pueden enviar
parmetros "por referencia" al enviar por valor la direccin de un dato (variable,
estructura, objeto), de manera que se pueda accesar directamente el rea de
memoria del dato del que se recibi su direccin.
C++ introduce parmetros por referencia reales. La manera en que se
definen es agregando el smbolo & de la misma manera que se coloca el *:
despus del tipo de dato en el prototipo y en la declaracin de la funcin.
Ejemplo:
#include <iostream.h>
#include <conio.h>
int porValor(int);
void porApuntador(int *);
void porReferencia( int &);
void main() {
clrscr();
int x=2;
cout << "x= " << x << " antes de llamada a porValor \n"
<< "Regresado por la funcin: "<< porValor(x)<<endl
<< "x= " << x << " despus de la llamada a
porValor\n\n";
int y=3;
cout << "y= " << y << " antes de llamada a
porApuntador\n";
porApuntador(&y);
cout << "y= " << y << " despus de la llamada a
porApuntador\n\n";
Carlos Alberto Fernndez y Fernndez
- 12 -
Programacin Orientada a Objetos con C++
int z=4;
cout << "z= " << z << " antes de llamada a porReferencia
\n";
porReferencia(z);
cout<< "z= " << z << " despus de la llamada a
porValor\n\n";
getch();
return;
}
Ejemplo:
// variable por referencia
#include <iostream.h>
#include <conio.h>
void main() {
clrscr();
y=10;
cout << "x= "<<x <<endl
<<"y= "<<y<<endl;
&y=&z;
cout << "z= "<<z <<endl
<<"y= "<<y<<endl;
y++;
cout << "z= "<<z <<endl
<<"y= "<<y<<endl;
getch();
return;
}
float *f;
f = (float *) malloc(sizeof(float));
. . .
free(f);
float *f;
f= new float;
. . .
delete f;
char *cad;
cad= new char [30];
. . .
delete [] cad;
Ejemplo 1:
#include <iostream.h>
main() {
int *p,*q;
if(!p) {
cout<<"No se pudo asignar memoria\n";
return 0;
}
*p=100;
cout<<endl<< *p<<endl;
Ejemplo 2:
#include <iostream.h>
void main() {
float *ap, *p=new float (3) ;
const int MAX=5;
ap= new float [MAX]; //asigna memoria
for(int i=0; i<MAX; i++)
ap[i]=i * *p;
for(i=0; i<MAX; i++)
cout<<ap[i]<<endl;
}
Ejemplo 3:
#include <iostream.h>
typedef struct {
int n1,
n2,
n3;
}cPrueba;
void main() {
cPrueba *pr1, *pr2;
delete pr2;
}
Plantillas o "templates"
Cada parmetro formal puede ser usado para sustituir a: tipos de datos bsicos,
estructurados o definidos por el usuario, tipos de los argumentos, tipo de regreso
de la funcin y para variables dentro de la funcin.
Ejemplo 1:
#include <iostream.h>
#include <conio.h>
void main(){
int a=10, b=20, c=0;
float x=44.1, y=22.3, z=0 ;
clrscr();
c=mayor(a, b);
z=mayor(x, y);
cout<<c<<" "<<z<<endl;
Consideraciones:
Cada parmetro formal debe aparecer en la lista de parmetros de la funcin al
menos una vez.
No puede repetirse en la definicin de la plantilla el nombre de un parmetro
formal.
Tener cuidado al manejar mas de un parmetro en los templates.
Ejemplo 2:
//prueba de templates o plantillas
#include <iostream.h>
#include <conio.h>
void main() {
const int contEnt=4, contFlot=5, contCar=10;
int ent[]={1,2,3,4};
float flot[]={1.1, 2.2, 3.3, 4.4, 5.5};
char car[]={"Plantilla"};
getch();
}
Ejemplo 3:
#include <iostream.h>
#include <conio.h>
void main(){
clrscr();
c=mayor(a, b);
z=mayor(x, y);
cout<<c<<" "<<z<<endl;
//sin error al aumentar un parmetro formal.
z=mayor(x,b);
cout<<z<<endl;
z=mayor(a,y); //regresa entero pues a es entero (tipo T es
entero para
cout<<z<<endl; // este llamado.
z=mayor(y, a);
cout<<z<<endl;
c=mayor(y, a);//regresa flotante pero la asignacin lo
corta en entero.
cout<<c<<endl;
getch();
}
Programacin no estructurada.
Comnmente, las personas empiezan a aprender a programar escribiendo
programas pequeos y sencillos consistentes en un solo programa principal.
Programacin procedural.
Con la programacin procedural se pueden combinar las secuencias de
instrucciones repetitivas en un solo lugar.
De este modo, un programa puede ser visto como una secuencia de llamadas
a procedimientos . El programa principal es responsable de pasar los datos a las
llamadas individuales, los datos son procesados por los procedimientos y, una vez
que el programa ha terminado, los datos resultantes son presentados.
As, el flujo de datos puede ser ilustrado como una grfica jerrquica, un
rbol, como se muestra en la figura para un programa sin subprocedimientos.
Programacin modular.
Cada mdulo puede contener sus propios datos. Esto permite que cada mdulo
maneje un estado interno que es modificado por las llamadas a procedimientos de
ese mdulo.
Sin embargo, solamente hay un estado por mdulo y cada mdulo existe
cuando ms una vez en todo el programa.
As, esto es exactamente del otro modo : Los datos especifican las
operaciones vlidas. Ahora, los mdulos agrupan representaciones de datos en
forma conjunta.
En contraste con las otras tcnicas, ahora tenemos una telaraa de objetos
interactuantes, cada uno de los cules manteniendo su propio estado.
Sin embargo, los problemas de la vida real son nebulosos y la primera cosa
que se tiene que hacer es tratar de entender el problema para separar los detalles
esenciales de los no esenciales :
Tratando de obtener tu propia perspectiva abstracta, o modelo, del
problema. Este proceso de modelado se llama abstraccin y se ilustra en la
Figura:
El modelo define una perspectiva abstracta del problema. Esto implica que
el modelo se enfoca solamente en aspectos relacionados con el problema y que
uno trata de definir propiedades del problema. Estas propiedades incluyen
por el problema.
Aspectos principales:
1) Objetos.
El objeto es la entidad bsica del modelo orientado a objetos.
El objeto integra una estructura de datos (atributos) y un comportamiento
(operaciones).
Se distinguen entre s por medio de su propia identidad, aunque internamente
los valores de sus atributos sean iguales.
2) Clasificacin.
Las clases describen posibles objetos, con una estructura y comportamiento
comn.
Los objetos que contienen los mismos atributos y operaciones pertenecen a la
misma clase.
La estructura de clases integra las operaciones con los atributos a los cuales se
aplican.
3) Instanciacin.
El proceso de crear objetos que pertenecen a una clase se denomina
instanciacin.
Pueden ser instanciados un nmero indefinido de objetos de cierta clase.
4) Generalizacin.
En una jerarqua de clases, se comparten atributos y operaciones entre clases
basados en la generalizacin de clases.
La jerarqua de generalizacin se construye mediante la herencia.
Las clases ms generales se conocen como superclases.
Las clases ms especializadas se conocen como subclases. La herencia puede
ser simple o mltiple.
5) Abstraccin.
La abstraccin se concentra en lo primordial de una entidad y no en sus
propiedades secundarias.
Adems en lo que el objeto hace y no en cmo lo hace.
Se da nfasis a cuales son los objetos y no cmo son usados.
6) Encapsulacin.
Encapsulacin o encapsulamiento es la separacin de las propiedades externas
de un objeto de los detalles de implementacin internos del objeto.
Al separar la interfaz del objeto de su implementacin, se limita la complejidad
al mostrarse slo la informacin relevante.
Disminuye el impacto a cambios en la implementacin, ya que los cambios a
las propiedades internas del objeto no afectan su interaccin externa.
7) Modularidad.
El encapsulamiento de los objetos trae como consecuencia una gran
modularidad.
Cada mdulo se concentra en una sola clase de objetos.
Los mdulos tienden a ser pequeos y concisos.
La modularidad facilita encontrar y corregir problemas.
La complejidad del sistema se reduce facilitando su mantenimiento.
8) Extensibilidad.
La extensibilidad permite hacer cambios en el sistema sin afectar lo que ya
existe.
Nuevas clases pueden ser definidas sin tener que cambiar la interfaz del resto
del sistema.
La definicin de los objetos existentes puede ser extendida sin necesidad de
cambios ms all del propio objeto.
9) Polimorfismo.
El polimorfismo es la caracterstica de definir las mismas operaciones con
diferente comportamiento en diferentes clases.
Se permite llamar una operacin sin preocuparse de cul implementacin es
requerida en que clase, siendo responsabilidad de la jerarqua de clases y no
del programador.
Objetos e instancias.
Def. Objeto. Un objeto es una instancia de una clase. Puede ser identificado
en forma nica por su nombre y define un estado, el cul es representado por los
valores de sus atributos en un momento en particular. [6]
Instanciacin.
Los objetos pueden ser creados de la misma forma que una estructura de
datos:
Clases en C++.
Sintaxis:
class <nombre_clase> {
<cuerpo de la clase>
};
Ejemplo:
class cEjemplo1 {
int x;
float y;
void fun(int a, float b) {
x=a;
y=b;
}
};
Una clase est formada por un conjunto de miembros que pueden ser datos,
funciones, clases anidadas, enumeraciones, tipos de dato, etc. . Por el momento
nos vamos a centrar en los datos y las funciones (atributos y mtodos).
Ejemplo:
class cEjemplo2{
int i;
int i; //error
int j;
int func(int, int);
}
1
Aunque existe el concepto de sobrecarga que se ver ms adelante
Carlos Alberto Fernndez y Fernndez
- 34 -
Programacin Orientada a Objetos con C++
Atributos miembro.
Todos los atributos que forman parte de una clase deben ser declarados
dentro de la misma.
Mtodos miembro.
Los mtodos al igual que los atributos, deber ser definidos en la clase, pero
el cuerpo de la funcin puede ir dentro o fuera de la clase. Si un mtodo se
declara completo dentro de la clase, se considera como inline.
Ejemplo:
//cdigo en ejemplo3.h
class cEjemplo3 {
public:
int x;
float y;
int funX(int a) {
x=a;
return x;
}
float funY(float);
};
Ejemplo:
//error en declaracin de un mtodo
class x{
public:
int a;
f();
};
Ejemplo:
//cdigo en ejemplo3.h
class cFecha {
private:
int dia;
int mes;
int an;
2
Un estado inconsistente sera ocasionado por una modificacin indebida de los datos, por ejemplo una modificacin sin
validacin.
Carlos Alberto Fernndez y Fernndez
- 37 -
Programacin Orientada a Objetos con C++
public:
char setDia(int); //poner da
int getDia(); //devuelve da
char setMes(int);
int getMes();
char setAn(int);
int getAnd();
};
Objetos de clase.
Hay que recordar que una de las caractersticas de los objetos es que cada
uno guarda un estado particular de acuerdo al valor de sus atributos3.
Un ejemplo completo:
#include <iostream.h>
#include <conio.h>
class cEjemplo3 {
public:
int i;
int j;
};
3
A diferencia de la programacin modular, donde cada mdulo tiene un solo estado. Aunque est caracterstica se puede lograr en
la programacin modular.
Carlos Alberto Fernndez y Fernndez
- 38 -
Programacin Orientada a Objetos con C++
void main() {
cEjemplo3 e3;
cEjemplo1 e1;
e1.i=10;
e1.j=20;
e2.i=100;
e2.j=20;
cout<<e1.i<<endl;
cout<<e2.i<<endl;
getch();
}
class cCola{
private:
int q[10];
int sloc, rloc;
public:
void ini() { //funcin en lnea
sloc=rloc=-1;
}
char set(int);
int get();
};
q[sloc]=val;
return 1;
}
int cCola::get(){
if(rloc==sloc)
cout<<"la cola esta vaca";
else {
rloc++;
return q[rloc];
}
}
void main(){
cCola a,b, *pCola= new cCola; // *pCola=NULL y despus
asignarle
clrscr();
a.ini();
b.ini();
pCola->ini();
a.set(1);
b.set(2);
pCola->set(3);
a.set(11);
b.set(22);
pCola->set(33);
cout<<a.get()<<endl;
cout<<a.get()<<endl;
cout<<b.get()<<endl;
cout<<b.get()<<endl;
cout<<pCola->get()<<endl;
cout<<pCola->get()<<endl;
getch();
delete pCola;
}
Nota: Otra forma de manejar los archivos .h, adems en el proyecto se puede
incluir el correspondiente obj para no proporcionar el cdigo.
#ifndef PILA_H
#define PILA_H
<definicin de la clase>
#endif
Carlos Alberto Fernndez y Fernndez
- 40 -
Programacin Orientada a Objetos con C++
Alcance de Clase.
Ejemplo:
class cMiClase{
public:
Int otraFuncion();
}
void main () {
cMiClase cM;
cM.otraFuncion();
Sobrecarga de operaciones.
Ejemplo:
class cMiClase{
int x;
public:
void modifica() {
x++;
}
void modifica(int y){
x=y*y;
}
}
Ejemplo 2:
//fuera de POO
#include <iostream.h>
void main() {
cout<<"10 elevado al cuadrado: "<<cuadrado(10)<<endl;
cout<<"10.5 elevado al cuadrado: "<<cuadrado(10.5)<<endl;
}
Constructores y destructores.
Constructor.
Ejemplo:
class cCola{
private:
int q[100];
int sloc, rloc;
public:
cCola( ); //constructor
void put(int);
int get( );
};
Destructor.
class cCola{
private:
int q[100];
int sloc, rloc;
public:
cCola( ); //constructor
~cCola(); //destructor
void put(int);
int get( );
};
cCola::~cCola( ){
cout<<"cola destruida\n";
}
class cCola{
Carlos Alberto Fernndez y Fernndez
- 44 -
Programacin Orientada a Objetos con C++
private:
int q[10];
int sloc, rloc;
char *nom;
public:
cCola(char *cad=NULL) { //funcion en linea
if(cad){ //cadena!=NULL
nom=new char[strlen(cad)+1];
strcpy(nom, cad);
}else
nom=NULL;
sloc=rloc=-1;
}
~cCola( ) {
if(nom){ //nom!=NULL
cout<<"Cola : "<<nom<<" destruida\n";
delete [] nom;
}
}
char set(int);
int get();
};
}
}
void main(){
cCola a("Cola a"),b("Cola b"),
*pCola= new cCola("Cola dinamica pCola");
clrscr();
a.set(1);
b.set(2);
pCola->set(3);
a.set(11);
b.set(22);
pCola->set(33);
cout<<a.get()<<endl;
cout<<a.get()<<endl;
cout<<b.get()<<endl;
cout<<b.get()<<endl;
cout<<pCola->get()<<endl;
cout<<pCola->get()<<endl;
getch();
delete pCola;
}
Miembros estticos.
Cada objeto tiene su propio estado, pero a veces es necesario tener valores
por clase y no por objeto. En esos casos es necesario tener atributos estticos que
sean compartidos por todos los objetos de la clase.
Clase
(Estado de la clase)
Objeto 1
(Estado del objeto)
Objeto 2
(Estado del objeto)
Objeto n
(Estado del objeto)
Ejemplo:
class cObjeto{
private:
char nombre[10];
static int numObjetos;
public:
cObjeto(char *cadena=NULL);
~cObjeto();
};
cObjeto::cObjeto(char *cadena){
if(cadena!=NULL)
strcpy(nombre, cadena);
else
nombre=NULL;
numObjetos++;
}
cObjeto::~cObjeto(){
numObjetos--;
}
Los atributos estticos deben de ser inicializados al igual que los atributos
constantes, fuera de la declaracin de la clase. Por ejemplo:
Ejemplo :
//prueba de miembros estticos
#include <iostream.h>
#include <stdio.h>
#include <conio.h>
#include <string.h>
class cPersona{
private:
static int nPersonas;
static const int MAX;
char *nombre;
public:
cPersona(char *c=NULL){
if(c!=NULL){
int cPersona::nPersonas=0;
const int cPersona::MAX=10;
void main() {
clrscr();
cout<<"Mximo de personas: "<<cPersona::getMax()<<endl;
cout<<"Nmero de personas:
"<<cPersona::getnPersonas()<<endl;
cPersona per1;
cout<<"Mximo de personas: "<<cPersona::getMax()<<endl;
cout<<"Nmero de personas:
"<<cPersona::getnPersonas()<<endl;
Objetos constantes.
Sintaxis:
const <clase> <lista de objetos>; const cHora h1(9,30,20);
Sintaxis:
Declaracin.
<tipo> <nombre> (<parmetros>) const;
4
Ayuda a cumplir el principio del mnimo privilegio, donde se debe restringir al mximo el acceso a los
datos cuando este acceso estara de sobra. [1]
Carlos Alberto Fernndez y Fernndez
- 50 -
Programacin Orientada a Objetos con C++
Ejemplo:
#include <iostream.h>
#include <conio.h>
#include <time.h>
#include <stdlib.h>
class cArr{
private:
int a[10];
public:
cArr(int x=0) {
for( int i=0; i<10; i++){
if (x==0)
x=random(10);
a[i]=x;
}
}
char set(int, int);
int get(int) const ;
int get(int);
};
void main(){
const cArr a(5),b;
cArr c;
randomize();
clrscr();
a.set(0,1); //error llamar a un mtodo no const
b.set(0,2); // para un objeto constante
c.set(0,3);
a.set(1,11);
b.set(1,22);
c.set(1,33);
cout<<a.get(0)<<endl;
cout<<a.get(1)<<endl;
cout<<b.get(0)<<endl;
cout<<b.get(1)<<endl;
cout<<c.get(0)<<endl;
cout<<c.get(1)<<endl;
getch();
}
Objetos compuestos.
Hay que tener en cuenta que pasa con los objetos que son parte del objeto
compuesto cuando ste ltimo se destruye. En general hay dos opciones:
Ejemplo:
class Nombre {
private:
char paterno[20],
materno[20],
nom[15];
public:
set(char *, char*, char *);
...
};
class Persona {
private:
int edad;
Nombre nombrePersona;
....
};
Sintaxis:
donde la lista de argumentos del objeto compuesto debe incluir a los argumentos
de los objetos componentes, para que puedan ser pasados en la creacin del
objeto.
Ejemplo:
#include <stdio.h>
#include <string.h>
#include <iostream.h>
class cNombre {
char *nombre,
*paterno,
*materno;
public:
cNombre(char *n, char *p, char*m){
nombre=new char[strlen(n)+1];
paterno=new char[strlen(p)+1];
materno=new char[strlen(m)+1];
strcpy(nombre, n);
strcpy(paterno, p);
strcpy(materno, m);
}
~cNombre(){
delete []nombre, paterno, materno;
cout<<"destructor de cNombre"<<endl;
}
};
class cPersona{
cNombre miNombre;
int edad;
public:
cPersona(char *n, char *p, char*m): miNombre(n, p, m){
edad=0;
}
};
void main() {
cPersona *per1;
per1= new cPersona("uno", "dos", "tres");
cPersona per2("carlos alberto", "fernandez y",
"fernandez");
delete per1;
}
Una clase puede estar relacionada con otra clase, o en la prctica un objeto
con otro objeto.
Ejemplo:
Una clase estudiante est relacionada con una clase Universidad.
Profesor Cubculo
Asociacin
B *pB;
};
class B{
//lista de atributos
A *pA;
};
Asociaciones reflexivas.
Si una clase mantiene una asociacin consigo misma se dice que es una
asociacin reflexiva.
Ejemplo: Persona puede tener relaciones entre si, si lo que nos interesa es
representar a las personas que guardan una relacin entre s, por ejemplo si son
parientes. Es decir, un objeto mantiene una relacin con otro objeto de la misma
clase.
Persona
Asociacin reflexiva
"uno a uno": donde dos objetos se relacionan de forma exclusiva, uno con el
otro.
Ejemplo:
Un alumno tiene una boleta de calificaciones.
"uno a muchos": donde uno de los objetos puede estar relacionado con
muchos otros objetos.
Ejemplo:
Un usuario de la biblioteca puede tener muchos libros prestados.
"muchos a muchos": donde cada objeto de cada clase puede estar relacionado
con muchos otros objetos.
Ejemplo:
Un libro puede tener varios autores, mientras que un autor puede tener
varios libros.
Departamento
Empleado Proyecto
class A{
...
B *pB;
};
class B{
A *p[5];
//
A **p;
}
(Persona)
(Compaia)
(Persona)
(Persona)
(Compaia)
(Persona)
Ejemplo:
Se muestra un cdigo simplificado para manejo de asociaciones.
Clase cLibro
class cPersona;
class cLibro {
public:
char nombre[10];
cPersona *pPersona;
cLibro();
~cLibro();
};
---
#include <stdio.h>
#include "cPersona.h"
#include "cLibro.h"
cLibro::cLibro(){
nombre[0]='\0';
pPersona=NULL;
}
cLibro::~cLibro(){
if(pPersona!=NULL)
for(int i=0; i<5; i++)
if (pPersona->pLibrosPres[i]==this)
pPersona->pLibrosPres[i]=NULL;
Clase cPersona
class cLibro;
class cPersona {
public:
cLibro *pLibrosPres[5];
cPersona();
~cPersona();
};
----
#include <stdio.h>
#include "clibro.h"
#include "cpersona.h"
cPersona::cPersona(){
int i;
cPersona::~cPersona(){
int i;
Constructor de Copia
Es til agregar a todas las clases un constructor de copia que reciba como
parmetro un objeto de la clase y copie sus datos al nuevo objeto.
Sintaxis:
Ejemplo:
class cArr{
private:
int a[10];
public:
cArr(int x=0) {
for( int i=0; i<10; i++){
if (x==0)
x=random(10);
a[i]=x;
}
}
cArr(const cArr &copia){ //constructor de copia
for( int i=0; i<10; i++)
a[i]=copia.a[i];
}
void main(){
cArr a(5);
randomize();
clrscr();
a.set(0,1);
a.set(1,11);
cout<<a.get(0)<<endl;
cout<<a.get(1)<<endl;
cArr d(a);
cout<<d.get(0)<<endl;
cout<<d.get(1)<<endl;
getch();
} Comentario: Eliminar este
ultimo (cAlumno y cLibro ) al
colocar este tema en el orden
adecuado
Sobrecarga de operadores.
Algunas restricciones:
. .* :: ?: sizeof
Ejemplo:
//programa de ejemplo de sobrecarga de operadores.
class punto {
float x, y;
public:
punto(float xx=0, float yy=0){
x=xx;
y=yy;
}
float magnitud();
punto operator =(punto);
punto operator +(punto);
punto operator -();
punto operator *(float);
punto operator *=(float);
punto operator ++();
int operator >(punto);
int operator <=(punto);
};
temp=punto(x*f, y*f);
return temp;
}
void main(){
punto a(1,1);
punto b;
punto c;
b++;
++b;
c=b;
c=a+b;
c=-a;
c=a*.5;
Ejercicio : Crear una clase cString para el manejo de cadenas. Tendr dos
atributos: apuntador a carcter y un entero tam, para almacenar el tamao de la
cadena. Sobrecargar operadores = (asignacin) e (==) igualdad. Usar un
programa de prueba.
La estructura ser la siguiente:
class cString{
char *s;
int tam;
public:
cString(char *=NULL);
cString(const cString &copia); //constructor de copia
~cString();
//sobrecarga de constructor de asignacin
const cString &operator =(const cString &);
//igualdad
int operator ==(const cString &) const ;
};
Vase que es posible asignar una cadena " " sin sobrecargar el operador de
asignacin, o comparar un objeto cString con una cadena. Esto se logra gracias a
que se provee de un constructor que convierte una cadena a un objeto cString. De
esta manera, este constructor de conversin es llamado automticamente, creando
un objeto temporal para ser comparado con el otro objeto. No es posible que la
cadena (o apuntador a char) vaya del lado izquierdo, pues se estara llamando a la
funcionalidad del operador para un apuntador a char.
class cString{
//operadores de insercin y extraccin de flujo
friend ostream &operator << (ostream &, const cString &);
friend istream &operator >> (istream &, cString &);
private:
char *s;
int tam;
public:
cString(char * =NULL); {
if(c==NULL){
s=NULL;
tam=0;
}
else {
tam=strlen(c);
s= new char[tam+1];
strcpy(s, c);
}
}
cString(const cString &copia){
s=NULL;
tam=0;
*this=copia;//se vale o no?
}
~cString(){
if(s!=NULL)
delete []s;
}
//igualdad
int operator ==(const cString &) const ;
//concatenacin
cString operator +(const cString &);
//concatenacin y asignacin
const cString &operator +=(const cString &);
cString::cString(char *c){
if(c==NULL){
s=NULL;
tam=0;
} else {
tam=strlen(c);
s= new char[tam+1];
strcpy(s, c);
}
}
tam=c.tam;
s= new char[tam+1];
strcpy(s, c.s);
}
return *this; //permite concatenacin de asignaciones
}
void main(){
clrscr();
cString a("AAA");
cString b("Prueba de cadena");
cString c(b);
/*es un error hacer una asignacin sin liberar memoria.
ese es el principal peligro de usar el operador
sobrecargado por default de asignacin*/
a=b;
b.copia("H o l a");
b=c+c;
b="nueva";
c+=c;
cString d("nueva cadena");
d+="Hola";
cString e;
e=d+"Adios";
d="coche";
int x=0;
x=d=="coche"; //Lo contrario no es vlido "coche"==d
char ch;
ch=d[7];
cin>>e>>d;
cout<<e<<d;
printf("fin");
}
class c1{
friend void miAmiga(int);
...
public:
...
};
class c1{
friend c2;
...
public:
...
};
Ejemplo 1:
void main(){
claseX pr;
Ejemplo 2:
class Linea;
class Recuadro {
friend int mismoColor(Linea, Recuadro);
private:
int color; //color del recuadro
int xsup, ysup; //esquina superior izquierda
int xinf, yinf; //esquina inferior derecha
public:
void ponColor(int);
void definirRecuadro(int, int, int, int);
void mostrarRecuadro(void);
};
class Linea{
friend int mismoColor(Linea, Recuadro);
private:
Carlos Alberto Fernndez y Fernndez
- 77 -
Programacin Orientada a Objetos con C++
int color;
int xInicial, yInicial;
int lon;
public:
void ponColor(int);
void definirLinea(int, int, int);
void mostrarLinea();
};
void Recuadro::mostrarRecuadro(){
int i;
textcolor(color);
gotoxy(xsup, ysup);
for(i=xsup; i<=xinf; i++)
cprintf("-");
gotoxy(xsup, yinf-1);
for(i=xsup; i<=xinf; i++)
cprintf("-");
gotoxy(xsup, ysup);
for(i=ysup; i<=yinf; i++){
cprintf("|");
gotoxy(xsup, i);
}
gotoxy(xinf, ysup);
for(i=ysup; i<=yinf; i++){
cprintf("|");
gotoxy(xinf, i);
}
}
xInicial=x;
yInicial=y;
lon=l;
}
void Linea::mostrarLinea(){
int i;
textcolor(color);
gotoxy(xInicial, yInicial);
for(i=0; i<lon; i++)
cprintf("-");
}
void main(){
Recuadro r;
Linea l;
clrscr();
r.definirRecuadro(10, 10, 15, 15);
r.ponColor(3);
r.mostrarRecuadro();
l.definirLinea(2, 2, 10);
l.ponColor(4);
l.mostrarLinea();
if(!mismoColor(l, r))
cout<<"No tienen el mismo color";
getch();
if(mismoColor(l, r))
cout<<"Tienen el mismo color";
getch();
}
Herencia.
Introduccin.
La herencia es un mecanismo potente de abstraccin que permite compartir
similitudes entre clases manteniendo al mismo tiempo sus diferencias.
Implementacin en C++.
Sintaxis general:
Ejemplo:
class cVehiculo{
int ruedas;
int pasajeros;
public:
void setRuedas(int);
int getRuedas();
void setPasajeros(int);
int getPasajeros();
};
int cVehiculo::getRuedas(){
Carlos Alberto Fernndez y Fernndez
- 82 -
Programacin Orientada a Objetos con C++
return ruedas;
}
int cVehiculo::getPasajeros(){
return pasajeros;
}
void cCamion::muestra(){
cout<<"Ruedas: "<< getRuedas()<<endl;
cout<<"Pasajeros: "<< getPasajeros()<<endl;
cout<<"Capacidad de carga: "<<getCarga()<<endl;
}
void main(){
cCamion ford;
ford.setRuedas(6);
ford.setPasajeros(3);
ford.setCarga(3200);
ford.muestra();
}
Tipo de Descripcin
acceso
private Un miembro privado nicamente puede ser utilizado por
los mtodos miembro y funciones amigas de la clase
donde fue declarado.
protected Un miembro protegido puede ser utilizado nicamente
por los mtodos miembro y funciones amigas de la clase
donde fue declarado o por los mtodos miembro y
funciones amigas de las clases derivadas.
El acceso protegido es como un nivel intermedio entre el
acceso privado y pblico.
public Un miembro pblico puede ser utilizado por cualquier
mtodo. Una estructura es considerada por C++ como
una clase que tiene todos sus miembros pblicos.
Ejemplo:
//acceso01
//ejemplo de control de acceso
class s{
char *f1();
int a;
protected:
int b;
int f2();
Carlos Alberto Fernndez y Fernndez
- 84 -
Programacin Orientada a Objetos con C++
private:
int c;
int f3();
public:
int d, f;
char *f4(int);
};
void main(){
s obj;
obj.f1(); //error
obj.a=1; //error
obj.f2();//error
obj.b=2; //error
obj.c=3; //error
obj.f3(); //error
obj.d=5;
obj.f4(obj.f);
}
Hasta ahora se han usado la herencia con un solo tipo de acceso, usando el
especificador public, los miembros pblicos de la clase base son miembros
pblicos de la clase derivada, los miembros protegidos permanecen protegidos
para la clase derivada.
Ejemplo:
//acceso02
//ejemplo de control de acceso en herencia
class cBase{
int a;
protected:
int b;
public:
int c;
};
void cDerivada::g(){
a=0; //error, es privado
b=1; //correcto, es protegido
c=2; //correcto, es pblico
}
Para accesar a los miembros de una clase base desde una clase derivada, se
pueden ajustar los permisos por medio de un calificador public, private o
protected.
Si una clase base es declarada como pblica de una clase derivada, los
miembros pblicos y protegidos son accesibles desde la clase derivada, no as los
miembros privados.
Si una clase base es declarada como privada de otra clase derivada, los
miembros pblicos y protegidos de la clase base sern miembros privados de la
clase derivada. Los miembros privados de la clase base permanecen inaccesibles.
Ejemplo de sintaxis:
class base {
...
};
...
};
class x{
public:
F();
};
void g( y *p){
pf(); //error
}
Si una clase base es declarada como protegida de una clase derivada, los
miembros pblicos y protegidos de la clase base, se convieten en miembros
protegidos de la clase derivada.
Ejemplo:
//acceso por herencia
//acceso03
#include <iostream.h>
class X{
protected:
int i;
int j;
public:
void preg_ij();
void pon_ij();
};
void X::preg_ij() {
cout<< "Escriba dos nmeros: ";
cin>>i>>j;
}
void X::pon_ij() {
cout<<i<<' '<<j<<endl;
}
void Y::hacer_k() {
k=i*j;
}
var.preg_ij();
var.pon_ij();
var.hacer_k();
cout<<var.preg_k()<<endl;
var2.f();
var2.pon_ij();
}
Ejemplo :
// POINT.H
// clase Point
#ifndef POINT_H
#define POINT_H
class Point {
friend ostream &operator<<(ostream &, const Point &);
public:
Point(float = 0, float = 0);
void setPoint(float, float);
float getX() const { return x; }
float getY() const { return y; }
protected:
float x, y;
};
#endif
Carlos Alberto Fernndez y Fernndez
- 91 -
Programacin Orientada a Objetos con C++
// POINT.CPP
#include <iostream.h>
#include "point.h"
Point::Point(float a, float b)
{
x = a;
y = b;
}
return output;
}
// CIRCLE.H
// clase Circle
#ifndef CIRCLE_H
#define CIRCLE_H
#include <iostream.h>
#include <iomanip.h>
#include "point.h"
void setRadius(float);
float getRadius() const;
#endif
// CIRCLE.CPP
#include "circle.h"
// salida en el formato:
// Center = [x, y]; Radius = #.##
ostream &operator<<(ostream &output, const Circle &c)
{
output << "Center = [" << c.x << ", " << c.y
<< "]; Radius = " << setiosflags(ios::showpoint)
<< setprecision(2) << c.radius;
return output;
}
//Prueba.cpp
// Probando apuntadores a clase base a apuntadores a clase
derivada
#include <iostream.h>
#include <iomanip.h>
#include "point.h"
#include "circle.h"
main()
{
Point *pointPtr, p(3.5, 5.3);
Circle *circlePtr, c(2.7, 1.2, 8.9);
cout << "Point p: " << p << "\nCircle c: " << c << endl;
return 0;
}
Ejemplo:
// POINT2.H
#ifndef POINT2_H
#define POINT2_H
class Point {
public:
Point(float = 0.0, float = 0.0);
~Point();
protected:
float x, y;
};
#endif
// POINT2.CPP
#include <iostream.h>
#include "point2.h"
Point::Point(float a, float b)
{
x = a;
y = b;
Point::~Point()
{
cout << "Destructor Point: "
<< '[' << x << ", " << y << ']' << endl;
}
// CIRCLE2.H
#ifndef CIRCLE3_H
#define CIRCLE3_H
#include "point2.h"
#include <iomanip.h>
#endif
// CIRCLE2.CPP
#include "circle2.h"
radius = r;
Circle::~Circle()
{
cout << "Destructor Circle: radio es "
<< radius << " [" << x << ", " << y << ']' << endl;
}
// Main.CPP
#include <iostream.h>
#include "point2.h"
#include "circle2.h"
main()
{
// Muestra llamada a constructor y destructor de Point
{
Point p(1.1, 2.2);
}
Redefinicin de mtodos
Ejemplo :
// EMPLOY.H
#ifndef EMPLOY_H
#define EMPLOY_H
class Employee {
public:
Employee(const char*, const char*);
void print() const;
~Employee();
private:
char *firstName;
char *lastName;
};
#endif
// EMPLOY.CPP
#include <string.h>
#include <iostream.h>
#include <assert.h>
#include "employ.h"
Employee::~Employee()
{
delete [] firstName;
delete [] lastName;
}
// HOURLY.H
#ifndef HOURLY_H
#define HOURLY_H
#include "employ.h"
#endif
// HOURLY_B.CPP
#include <iostream.h>
#include <iomanip.h>
#include "hourly.h"
main()
{
HourlyWorker h("Bob", "Smith", 40.0, 7.50);
h.print();
return 0;
}
Herencia Mltiple.
Sintaxis:
class <nombre clase derivada> : <clase base 1> , <clase
base 2>, ...<clase base n> {
...
};
Ejemplo:
class A{
public:
int i;
int a();
};
class B{
public:
int j;
int b();
};
class C{
public:
int k;
int c();
};
};
void main() {
D var1;
var1.a();
var1.b();
var1.c();
var1.d();
}
Otro ejemplo :
// BASE1.H
#ifndef BASE1_H
#define BASE1_H
class Base1 {
public:
Base1(int x) { value = x; }
int getData() const { return value; }
protected: int value; };
#endif
// BASE2.H
#ifndef BASE2_H
#define BASE2_H
class Base2 {
public:
Base2(char c) { letter = c; }
char getData() const { return letter; }
protected:
char letter;
};
#endif
// DERIVED.H
Carlos Alberto Fernndez y Fernndez
- 102 -
Programacin Orientada a Objetos con C++
#ifndef DERIVED_H
#define DERIVED_H
#include "base1.h"
#include "base2.h"
// herencia mltiple
class Derived : public Base1, public Base2 {
friend ostream &operator<<(ostream &, const Derived &);
public:
Derived(int, char, float);
float getReal() const;
private:
float real;
};
#endif
// DERIVED.CPP
#include <iostream.h>
#include "derived.h"
return output;
}
// main.CPP
#include <iostream.h>
#include <conio.h>
#include "base1.h"
#include "base2.h"
#include "derived.h"
main(){
Base1 b1(10), *base1Ptr; Base2 b2('Z'), *base2Ptr;
Derived d(7, 'A', 3.5); clrscr();
cout << "Objeto b1 contiene entero "
<< b1.getData()
<< "\nObjeto b2 contiene caracter "
<< b2.getData()
<< "\nObjeto d contiene:\n" << d;
cout << "\n\nmiembros de clase derivada pueden ser"
<< " accesados individualmente:\n"
<< " Entero: " << d.Base1::getData()
<< "\n Caracter: " << d.Base2::getData()
<< "\Nmero real: " << d.getReal() << "\n\n";
// es un error?: cout<<d.getData();
cout << "Miembros derivados pueden ser tratados como "
<< "objetos de su clase base:\n";
base1Ptr = &d;
cout << "base1Ptr->getData() "
<< base1Ptr->getData();
base2Ptr = &d;
cout << "\nbase2Ptr->getData() "
<< base2Ptr->getData() << endl;
return 0;
}
Ambigedades.
Ejemplo:
void f( D *p) {
p->b=0; //ambiguo
}
void main(){
D obj;
f(&obj);
}
B C
class A{
public:
int next;
};
class B: public A{
};
class C: public A{
};
class D: public B, public C {
int g();
};
int D::g(){
//next=0; Error: asignacin ambigua
return B::next == C::next;
}
class E: public D{
public:
int x;
int getx(){
return x;
}
};
void main(){
D obj;
E obje;
obj.B::next=10;
obj.C::next=20;
// obj.A::next=11; no se vale
// obj.next=22;
cout<<"next de B: "<<obj.B::next<<endl;
cout<<"next de C: "<<obj.C::next<<endl;
obje.x=0;
obje.B::next=11;
obje.C::next=22;
cout<<"obje next de B: "<<obje.B::next<<endl;
cout<<"obje next de C: "<<obje.C::next<<endl;
}
Este programa hace que las instancias de la clase D tengan objetos de clase
base duplicados y provoca los accesos ambiguos. Este problema se resuelve con
herencia virtual.
En este caso las clases B y c deben declarar a la clase A como clase base
virtual:
Constructores.
Para ejecutar los constructores de las clases base, pasando los argumentos,
es necesario especificarlos despus de la declaracin de la funcin de
construccin de la clase derivada, separados por coma.
Sintaxis general:
<Constructor clase derivada>(<argumentos> : <base1>
(<argumentos>), <base2> (<argumentos>), ... , <basen>
(<argumentos>) {
...
}
Las funciones virtuales son muy especiales, debido a que cuando una
funcin es accesada por un apuntador a una clase base, y este esta haciendo
referencia a un objeto de una clase derivada, el programa determina en tiempo de
ejecucin a que funcin llamar, de acuerdo al tipo de objeto al que se apunta. Esto
se conoce como ligadura tarda y el compilador de C++ incluye en el cdigo
mquina el manejo de ese tipo de asociacin de mtodos.
Sintaxis:
class base {
Virtual <tipo> <mtodo> (<parmetros);
};
Ejemplo:
class base {
public:
virtual void quien(){
cout<<"base\n";
}
};
void main() {
base objBase, *pBase;
primera obj1;
segunda obj2;
tercera obj3;
cuarta obj4;
pBase=&objBase;
pBase->quien();
pBase=&obj1;
pBase->quien();
pBase=&obj2;
pBase->quien();
pBase=&obj3;
pBase->quien();
pBase=&obj4;
pBase->quien();
Hay que hacer notar que las funciones virtuales puede seguirse usando sin
apuntadores, mediante un objeto de la clase.
Carlos Alberto Fernndez y Fernndez
- 111 -
Programacin Orientada a Objetos con C++
Si se declara en una clase derivada un mtodo con otro tipo de dato como
retorno, el compilador manda un error, ya que esto no es permitido. Si se declara
un mtodo con el mismo nombre pero diferentes parmetros, la funcin virtual
queda desactivada de ese punto hacia abajo en la jerarqua de herencia.
Existen clases que son tiles para representar una estructura en particular,
pero que no van a tener la necesidad de generar objetos directamente a partir de
esa clase, estas se conocen como clases abtractas, o mejor dicho como clases base
abstractas, puesto que sirven para definir una estructura jerarquica.
La clase base abstracta entonces, tiene como objetivo proporcionar una clase
base que ayude al modelado de la jerarqua de herencia, aunque esta sea muy
general y no sea prctico tener instancias de esa clase.
Es importante tener en cuenta que una clase sigue siendo abstracta hasta que
no se implemente la funcin virtual pura, en una de las clases derivadas. Si no se
Polimorfismo.
Destructores virtuales.
class Employee {
public:
Employee(const char *, const char *);
~Employee();
const char *getFirstName() const;
const char *getLastName() const;
#endif
// EMPLEADO.CPP
#include <iostream.h>
#include <string.h>
#include <assert.h>
#include "empleado.h"
Employee::~Employee()
{
delete [] firstName;
delete [] lastName;
}
return firstName;
}
// JEFE.H
// Clase drivada de empleado
#ifndef JEFE_H
#define JEFE_H
#include "empleado.h"
#endif
// JEFE.CPP
#include <iostream.h>
#include "jefe.h"
void Boss::setWeeklySalary(float s)
{ weeklySalary = s > 0 ? s : 0; }
// COMIS.H
// Trabajador por comisin derivado de Empleado
#ifndef COMIS_H
#define COMIS_H
#include "empleado.h"
#endif
// COMIS.CPP
#include <iostream.h>
#include "comis.h"
void CommissionWorker::setSalary(float s)
{ salary = s > 0 ? s : 0; }
void CommissionWorker::setCommission(float c)
{ commission = c > 0 ? c : 0; }
void CommissionWorker::setQuantity(int q)
{ quantity = q > 0 ? q : 0; }
// PIEZA.H
// Trabajador por pieza derivado de Empleado
#ifndef PIECE1_H
#define PIECE1_H
#include "empleado.h"
#endif
// PIEZA.CPP
#include <iostream.h>
#include "pieza.h"
void PieceWorker::setWage(float w)
{ wagePerPiece = w > 0 ? w : 0; }
void PieceWorker::setQuantity(int q)
{ quantity = q > 0 ? q : 0; }
// HORA.H
// Trabajador por hora derivado de Empleado
#ifndef HOURLY1_H
#define HOURLY1_H
#include "empleado.h"
#endif
// HORA.CPP
#include <iostream.h>
#include "hora.h"
void HourlyWorker::setHours(float h)
{ hours = h >= 0 && h < 168 ? h : 0; }
// main.CPP
#include <iostream.h>
#include <iomanip.h>
#include "empleado.h"
#include "jefe.h"
#include "comis.h"
#include "pieza.h"
#include "hora.h"
main()
{
// formato de salida
cout << setiosflags(ios::showpoint) << setprecision(2);
class Shape {
public:
virtual float area() const { return 0.0; }
virtual float volume() const { return 0.0; }
virtual void printShapeName() const = 0; // virtual pura
};
#endif
// Punto.H
#ifndef Punto_H
#define Punto_H
#include <iostream.h>
#include "figura.h"
#endif
// Punto.CPP
#include <iostream.h>
#include "punto.h"
Point::Point(float a, float b)
{
x = a;
y = b;
}
// Circulo.H
#ifndef Circulo_H
#define Circulo_H
#include "punto.h"
void setRadius(float);
float getRadius() const;
virtual float area() const;
virtual void printShapeName() const { cout << "Circulo: ";
}
private:
float radius;
};
#endif
// Circulo.CPP
#include <iostream.h>
#include <iomanip.h>
#include "circulo.h"
return output;
}
// Cilindro.H
#ifndef Cilindro_H
#define Cilindro_H
#include "circulo.h"
void setHeight(float);
virtual float area() const;
virtual float volume() const;
#endif
// Cilindro.CPP
#include <iostream.h>
#include <iomanip.h>
#include "cilindro.h"
void Cylinder::setHeight(float h)
{ height = h > 0 ? h : 0; }
// main.CPP
//include...
main(){
Point point(7, 11);
Circle circle(3.5, 22, 8);
Cylinder cylinder(10, 3.3, 10, 10);
circle.printShapeName();
cout << circle << endl;
cylinder.printShapeName();
cout << cylinder << "\n\n";
cout << setiosflags(ios::showpoint) << setprecision(2);
Shape *ptr; // apuntador de clase base
ptr = &circle;
ptr->printShapeName();
cout << "x = " << circle.getX() << "; y =" << circle.getY()
<< "\nArea = " << ptr->area()
<< "\nVolumen = " << ptr->volume() << "\n\n";
ptr = &cylinder;
ptr->printShapeName(); // dynamic binding
cout << "x = " << cylinder.getX() << "; y = " <<
cylinder.getY()
<< "\nArea = " << ptr->area()
<< "\nVolumen = " << ptr->volume() << endl;
return 0;
}
Plantillas de clase.
Ejemplo:
// stack.h
// Clase de plantilla Pila
#ifndef TSTACK1_H
#define TSTACK1_H
#include <iostream.h>
#endif
while ( doubleStack.push( f ) ) {
cout << f << ' ';
f += 1.1;
}
while ( doubleStack.pop( f ) )
cout << f << ' ';
while ( intStack.push( i ) ) {
cout << i << ' ';
++i;
}
while ( intStack.pop( i ) )
cout << i << ' ';
Una plantilla de clase se puede derivar de una clase que no sea plantilla.
Una clase que no sea de plantilla se puede derivar de una plantilla de clase.
Manejo de Excepciones.
Introduccin.
Excepciones en C++.
throw: Esta instruccin seguida por una expresin de un cierto tipo, genera
una excepcin del tipo de la expresin. Esta instruccin debera ser
ejecutada dentro de algn bloque try, de manera directa o indirecta:
throw "Se genera una excepcin de tipo char *";
Bibliografa