Está en la página 1de 38

C++

Tutorial 1
Introducción a la
Programación Orientada a
Objetos
C++. Tutorial 1 Introducción POO

1. Introducción. ......................................................................................................................... 3
2. Conceptos orientados a objetos. .......................................................................................... 4
2.1. Abstracción de datos. .................................................................................................... 4
2.2. Objeto............................................................................................................................ 4
2.3. Atributos........................................................................................................................ 5
2.4. Mensajes y métodos. .................................................................................................... 5
2.5. Encapsulación. ............................................................................................................... 5
2.6. Clases............................................................................................................................. 5
2.7. Herencia de clases. ........................................................................................................ 5
2.8. Polimorfismo. ................................................................................................................ 6
3. E/S por consola de C++.......................................................................................................... 8
4. Comentarios en C++. ............................................................................................................. 9
5. Definición de clases. ............................................................................................................ 10
6. Introducción a la sobrecarga de funciones. ........................................................................ 13
7. Funciones constructoras y destructoras. ............................................................................ 14
8. Constructores con parámetros. .......................................................................................... 16
9. Punteros a objeto. ............................................................................................................... 18
10. Clases, estructuras y uniones en C++. ............................................................................. 19
11. Funciones insertadas. ...................................................................................................... 20
12. Inserción automática....................................................................................................... 21
13. Asignación de objetos. .................................................................................................... 22
14. Paso de objetos a funciones............................................................................................ 23
15. Objetos devueltos por funciones. ................................................................................... 24
16. Funciones amigas. ........................................................................................................... 25
17. Arrays de objetos ............................................................................................................ 26
18. Uso de punteros a objetos. ............................................................................................. 28
19. El puntero "THIS"............................................................................................................. 29
21. Asignación dinámica de memoria en C++. ...................................................................... 30
22. Referencias. ..................................................................................................................... 33
22.1. Paso de referencias a objetos. ................................................................................ 34
22.2. Devolución de referencias....................................................................................... 36
22.3. Referencias independientes. ................................................................................... 38

2 Francisco Javier Cabrerizo Membrilla (fjavier.cabrerizo@outlook.es)


C++ Tutorial 1 Introducción POO.

1. Introducción.

La POO (Programación Orientada a Objetos) es un nuevo paradigma de la programación.


Esto significa que es una nueva forma de organizar el conocimiento y de pensar sobre
lo que significa programar y sobre cómo se estructura la información dentro del
ordenador.
Tendremos entidades a las que llamaremos objetos. Los objetos se comunican con
otros objetos mediante mensajes. Un mensaje le dice a un objeto qué acción debe
iniciar, es decir, qué método debe ejecutar. Los objetos tienen unas características y un
comportamiento y entenderán unos mensajes determinados. Agruparemos en lo que
llamaremos clases a todos aquellos objetos con características y comportamiento
similares.
Podremos hacer especializaciones de tal forma que tendremos una jerarquía de clases
y las clases de niveles más bajos podrán usar datos y comportamiento de las clases más
altas. Es lo que llamaremos herencia.
Podremos crear cuantos objetos y clases deseemos, asignándoles unas características y
un comportamiento. No tendremos que conocer con detalle los pasos o el método que
sigue un objeto para dar respuesta a un mensaje. Hablamos entonces de abstracción de
datos y de encapsulación y ocultamiento de la información.

Francisco Javier Cabrerizo Membrilla (fjavier.cabrerizo@outlook.es) 3


C++. Tutorial 1 Introducción POO

2. Conceptos orientados a objetos.

Los principales conceptos relacionados con la Programación Orientada a Objetos son:


• abstracción de datos
• objetos
• clases
• atributos
• mensajes y métodos
• encapsulación
• polimorfismo o sobrecarga de funciones y operadores - herencia

2.1. Abstracción de datos.


La abstracción consiste en particionar un área de conocimiento y centrar nuestra
atención en algo concreto.
En los lenguajes de programación se usan dos mecanismos para la abstracción:
a) Abstracción por parametrización: se generaliza un procedimiento que se aplica
muchas veces a objetos diferentes y se representa en un solo procedimiento al
que se le pasan unos parámetros.
b) Abstracción por especificación: consiste en considerar sólo el comportamiento
que debe tener un procedimiento. A una especificación le podemos asociar
infinitas implementaciones a las que supondremos un comportamiento similar.
Tenemos dos tipos de abstracción según el elemento de programa al que afecten:
a) Procedimental: se considera que un procedimiento se comporta como una
operación simple.
b) De datos: es un nivel más alto y se considera como una unidad a una serie de
datos junto con una serie de operaciones que permiten manejarlos. Se habla
de tipo abstracto de datos (TAD). Los TAD se pueden instanciar.
Con estos dos tipos de abstracción se usa simultáneamente parametrización y
especificación.
En P.O.O. se utilizan TAD con abstracción por especificación. La idea es poder cambiar
la implementación de un TAD sin tener que cambiar nada en los programas u otros TDA
que lo usen.

2.2. Objeto.
Se corresponde con una entidad del mundo real. Tiene dos partes: una estructura de
datos y unas operaciones que manejan esa estructura, llamadas métodos. Un objeto
contiene atributos, a los que llamaremos variables de instancia. El objeto tiene una
parte visible y una parte oculta. En la parte visible, llamada interfaz o protocolo del
objeto, sólo vemos los nombres de los mensajes que el objeto entiende. En la parte
oculta están la implementación de esos métodos y los atributos.

4 Francisco Javier Cabrerizo Membrilla (fjavier.cabrerizo@outlook.es)


C++ Tutorial 1 Introducción POO.

2.3. Atributos.
Dos objetos tendrán, en principio, distinto valor en sus atributos. No se accede a los
atributos directamente, sino con los métodos del protocolo del objeto. Un atributo
puede tomar un valor o un conjunto de valores. Los atributos son también objetos.
Un objeto tiene una identidad: aunque cambien los valores de sus atributos, el objeto
sigue siendo siempre el mismo.

2.4. Mensajes y métodos.


Un objeto se comunica con otros objetos mediante mensajes. Un mensaje implica la
realización de una acción, es decir, la ejecución de un método. Los métodos operan
sobre los valores de un atributo y determinan el comportamiento de un objeto. Un
objeto puede entender varios mensajes.

2.5. Encapsulación.
Es el mecanismo que agrupa el código y los datos que maneja y los mantiene protegidos
frente a cualquier interferencia y mal uso. Un objeto es por tanto, el dispositivo que
soporta encapsulación. Un objeto oculta parte de su información a otros objetos. Sólo
se puede acceder a un objeto a través de los mensajes de su propia interfaz. Los
atributos y métodos están integrados en un objeto de tal forma que un objeto sólo
puede modificar sus propios atributos con sus propios métodos. Por esto, los atributos
y los métodos están almacenados físicamente en un mismo módulo de programación,
es decir, encapsulados.

2.6. Clases.
Todos los objetos con los mismos atributos y que entienden los mismos mensajes se
agrupan en una clase. Las instancias o ejemplares de una clase son los objetos.
Una clase es también un objeto, y por tanto debe ser instancia, a su vez, de una clase a
la que llamaremos metaclase. También tiene variables y métodos que se llaman
variables de clase y métodos de clase. Las variables de clase son compartidas por todos
los objetos de una clase. Entre los métodos de clase destacan los de creación de
instancias de una clase.

2.7. Herencia de clases.


Se establece una jerarquía de clases en la que una clase hereda de una clase superior
sus atributos y sus métodos. A la clase superior se le llama clase base y a la clase que
hereda se le llama clase derivada. Es una relación de especialización, llamada relación
ES-UN. Significa esto que los objetos de una clase entenderán los mismos mensajes y
tendrán los mismos atributos que los objetos de su clase base (superclase).

Francisco Javier Cabrerizo Membrilla (fjavier.cabrerizo@outlook.es) 5


C++. Tutorial 1 Introducción POO

Además, a una clase puede añadirse nuevos métodos y nuevos atributos, o anular los
métodos de su clase base, o redefinir dichos métodos.
La relación de herencia es ascendente: una clase hereda de su clase base que a su vez
también hereda de su clase base y así sucesivamente.
Para visualizar la relación de herencia utilizaremos grafos o árboles de herencia.
C++ tiene herencia múltiple, esto quiere decir que una clase puede heredar atributos y
métodos de más de una clase base.

2.8. Polimorfismo.
Un mismo mensaje puede ser válido para más de una clase porque su implementación
puede ser distinta. En realidad podremos tener varios métodos para un mismo mensaje.
Cuando ocurre esto decimos que hay polimorfismo o sobrecarga de funciones. Lo
mismo ocurre con el nombre de los atributos. El polimorfismo se puede aplicar tanto a
funciones como a operadores, en el segundo caso hablaremos de sobrecarga de
operadores.
Todos los lenguajes de POO, incluyendo C++, comparten las tres características
siguientes: encapsulación, polimorfismo y herencia.
Ejemplo:
#include <iostream>
class rectangulo
{
private:
int ancho, largo;
public:
void intro(int a, int b); int area ();
int perimetro ();
};

void rectangulo::intro(int a, int b)


{
ancho=a;
largo=b;
}
int rectangulo::area ()
{
return (ancho * largo);
}
int rectangulo::perimetro ()
{
return (2 * (ancho + largo));
}

int main (void)


{
rectangulo rect;
rect.intro(5,4);
cout << rect.area ();
cout << rect.perimetro ();
return 0;
}

6 Francisco Javier Cabrerizo Membrilla (fjavier.cabrerizo@outlook.es)


C++ Tutorial 1 Introducción POO.

En un objeto los atributos y los métodos están almacenados físicamente en un mismo


módulo de programación, es decir, encapsulados.
En un objeto los atributos y los métodos, o ambos, pueden ser privados para ese objeto
o públicos. Los atributos y/o los métodos privados sólo los conoce y son accesibles por
otra parte del objeto. Cuando los métodos y/o los atributos son públicos, son accesibles
desde cualquier punto del programa.

Francisco Javier Cabrerizo Membrilla (fjavier.cabrerizo@outlook.es) 7


C++. Tutorial 1 Introducción POO

3. E/S por consola de C++.

En C++, la E/S se realiza usando operadores de E/S en vez de funciones de E/S. El


operador de salida es << y el operador de entrada >>.

En general para visualizar algo por consola, el formato será:


cout << expresión;

donde cout es un flujo predefinido que se enlaza automáticamente con la consola


cuando un programa C++ comienza su ejecución; y expresión puede ser cualquier
expresión válida de C++ incluyendo otra expresión de salida.
Ejemplo:

cout << "El valor de n es " << n;

Para introducir valores desde teclado el formato es:


cin >> variable;

donde cin es un flujo predefinido que se enlaza automáticamente con el teclado.


Para usar los operadores de E/S de C++, se debe incluir en el programa el archivo de
cabecera iostream.

8 Francisco Javier Cabrerizo Membrilla (fjavier.cabrerizo@outlook.es)


C++ Tutorial 1 Introducción POO.

4. Comentarios en C++.

En C++ se pueden incluir comentarios en el programa de dos formas diferentes:


1. Se puede utilizar el estándar, es decir, el mecanismo de comentarios al estilo de
C, a saber, iniciar un comentario con /* y terminarlo con */.
2. Usar el comentario de línea única que comienza con el símbolo // y termina al
final de la línea.

Francisco Javier Cabrerizo Membrilla (fjavier.cabrerizo@outlook.es) 9


C++. Tutorial 1 Introducción POO

5. Definición de clases.

Quizás la característica más importante de C++ es la clase. La clase es el mecanismo que


se usa para crear objetos.
La sintaxis de una declaración de clase es similar a la de una estructura y su formato
general es el siguiente:
class nom_clase
{
private:
funciones y variables privadas de la clase;
public:
funciones y variables públicas de la clase;
}lista de objetos;

Las funciones y variables declaradas dentro de una declaración de clase, se dice que son
miembros de esa clase. Por omisión, todas las funciones y variables declaradas en una
clase son privadas para esa clase. Esto significa, que sólo son accesibles por otros
miembros de esa clase. Todas las funciones y variables declaradas tras el especificador
public son públicas y por tanto, accesibles tanto por los miembros de la clase como por
cualquier otra parte del programa que contiene la clase.
Las funciones declaradas como parte de una clase se llaman funciones miembro. Para
definir una función miembro, se debe enlazar el nombre tipo de la clase de la que es
parte la función miembro con el nombre de la función. Esto se hace precediendo el
nombre de la función con el nombre de clase seguido de dos símbolos de dos puntos.
El formato general para definir una función miembro es el siguiente:
tipo nom_clase::nom_función(lista-parámetros)
{
<instrucciones>;
}

Para crear un objeto de una determinada clase se utiliza el nombre de dicha clase como
un especificador de tipo:
nom_clase lista_de_objetos;

Una vez creado un objeto de clase, el programa puede referenciar sus miembros
públicos usando el operador punto de la misma forma en que se accede a los miembros
de la estructura.

10 Francisco Javier Cabrerizo Membrilla (fjavier.cabrerizo@outlook.es)


C++ Tutorial 1 Introducción POO.

Ejemplo:
#include <iostream>
class op_aritméticas
{
private:
int op1, op2;
public:
intro (int a, int b);
int suma();
int resta();
float multiplica();
float divide();
};

op_aritméticas::intro (int a, int b)


{
op1 = a;
op2 = b;
}

int op_aritméticas::suma()
{
return (op1 + op2);
}

int op_aritméticas::resta()
{
return (op1 - op2);
}

float op_aritméticas::multiplica()
{
return (op1 * op2);
}
float op_aritméticas::divide()
{
return (op1 / op2);
}
main()
{
int a, b;
op_aritméticas ob;
cout << "Operador 1: ";
cin >> a;
cout << "Operador 2: ";
cin >> b;
ob.intro (a,b);
cout << a << " + " << b << " = " << ob.suma();
cout << a << " - " << b << " = " << ob.resta();
cout << a << " * " << b << " = " << ob.multiplica();
cout << a << " / " << b << " = " << ob.divide();
}

Francisco Javier Cabrerizo Membrilla (fjavier.cabrerizo@outlook.es) 11


C++. Tutorial 1 Introducción POO

Ejemplo. Creación de una clase Triángulo

#include <iostream>
class triangulo
{
private:
int base, altura;
public:
intro (int a, int b);
float área();
};

triangulo::intro (int a, int b)


{
base = a;
altura = b;
}
float triangulo::area()
{
return ((base * altura) / 2);
}

int main()
{
int a, b;
triangulo ar;
cout << "Base: ";
cin >> a;
cout << "Altura: ";
cin >> b; ar.intro(a,b);
cout << "El área de " << a << "y " << b << "es: " << ar.area();
return 0;
}

12 Francisco Javier Cabrerizo Membrilla (fjavier.cabrerizo@outlook.es)


C++ Tutorial 1 Introducción POO.

6. Introducción a la sobrecarga de funciones.

Después de las clases, quizás la característica más importante y llamativa de C++ es la


sobrecarga de funciones.
En C++ dos o más funciones pueden compartir el mismo nombre en tanto en cuanto
difiera el tipo de sus argumentos o el número de los mismos o ambos. Cuando dos o
más funciones comparten el mismo nombre, se dice que están sobrecargadas.

En C++ también es posible la sobrecarga de operadores. Esta característica también es


común al C.

Francisco Javier Cabrerizo Membrilla (fjavier.cabrerizo@outlook.es) 13


C++. Tutorial 1 Introducción POO

7. Funciones constructoras y destructoras.

Prácticamente cada objeto que se crea va a necesitar algún tipo de inicialización. Para
tratar esta situación, C++ permite incluir una función constructora en una declaración
de clase. A un constructor de clase se le llama cada vez que se crea un objeto de esa
clase. De esta manera, cualquier inicialización que sea necesaria en un objeto la puede
realizar automáticamente la función constructora.
Una función constructora tiene el mismo nombre que la clase de la que es parte y no
tiene tipo devuelto.
Ejemplo:
#include <iostream>
class pila
{
private:
int p[10];
int tope;
public:
pila();
PUSH (int n);
POP ();
};

pila::pila()
{
int i;
tope = 0;
for (i=0; i<10; i++)
p[i] = 0;
}

Es incorrecto que un constructor tenga un tipo devuelto.


Para objetos globales, a un constructor de objetos se le llama una sola vez, cuando el
programa comienza la ejecución. Para objetos locales, al constructor se le llama cada
vez que se ejecuta la sentencia de declaración.
El complemento de un constructor es el destructor. A esta función se le llama cuando
se destruye un objeto. El nombre de un destructor es el nombre de la clase a la que
pertenece precedido por el carácter ~.

14 Francisco Javier Cabrerizo Membrilla (fjavier.cabrerizo@outlook.es)


C++ Tutorial 1 Introducción POO.

Ejemplo:
#include <iostream>
class ejemplo
{
private:
int *n;
public:
ejemplo();
~ejemplo();
};

ejemplo::ejemplo()
{
n = (int *) malloc (sizeof(int));
}

ejemplo::~ ejemplo()
{
free (n);
}

Al destructor de la clase se le llama cuando se destruye un objeto. Los objetos locales


se destruyen cuando se salen del ámbito, mientras que los objetos globales sólo se
destruyen cuando finaliza el programa.

Francisco Javier Cabrerizo Membrilla (fjavier.cabrerizo@outlook.es) 15


C++. Tutorial 1 Introducción POO

8. Constructores con parámetros.

Es posible pasar argumentos a una función constructora. Para permitir esto,


simplemente debemos añadir los parámetros adecuados a la declaración y definición
de la función constructora. Después, cuando declaremos un objeto de dicha clase,
deberemos especificar los parámetros como argumentos.
Ejemplo:
#include <iostream>
class rectángulo
{
private:
int ancho, largo;
public:
rectangulo (int a, int b);
int area();
int perimetro();
};

rectangulo::rectangulo (int a, int b)


{
ancho = a;
largo = b;
}

int rectangulo::area()
{
return (ancho * largo);
}

int rectangulo::perimetro()
{
return (2 * (ancho + largo));
}

int main()
{
int largo, ancho;
clrscr();
cout << "Introduce largo: ";
cin >> largo;
cout << "Introduce ancho: ";
cin >> ancho;
rectangulo obj(largo, ancho);
cout << "Área = " << obj.area();
cout << "Perímetro = " << obj.perímetro();
getch();
return 0;
}

Ejemplo. Creación de una clase llamada box, cuya función constructora recibe tres
valores de tipo entero, que representen la longitud de los lados del paralelepipedo.
También se va a crear una función miembro llamada vol que muestre el volumen de
cada objeto de la clase box.

16 Francisco Javier Cabrerizo Membrilla (fjavier.cabrerizo@outlook.es)


C++ Tutorial 1 Introducción POO.

#include <iostream.h>
#include <conio.h>
class box
{
private:
int a, b, c;
public:
box (int largo, int ancho, int alto);
int vol();
};

box::box (int largo, int ancho, int alto)


{
a = largo;
b = ancho;
c = alto;
}

int box::vol ()
{
return (a * b * c);
}

Francisco Javier Cabrerizo Membrilla (fjavier.cabrerizo@outlook.es) 17


C++. Tutorial 1 Introducción POO

9. Punteros a objeto.

Es posible acceder a un miembro de un objeto a través de un puntero a ese objeto.


Cuando sea este el caso, se emplea el operador flecha (->) en lugar del operador punto.
Un puntero a objeto se declara exactamente igual que se declara un puntero a cualquier
otro tipo de variable. Se especifica su nombre de clase y luego se precede el nombre de
variable con un asterisco. Para obtener la dirección de un objeto, se precede al objeto
con el operador &.
Ejemplo:

int main()
{
rectangulo ob1(5,4), *ob2;
ob2 = &ob1;
cout << "Área = " << ob1.área();
cout << "Perímetro = "" << ob2->perímetro();
return 0;
}

18 Francisco Javier Cabrerizo Membrilla (fjavier.cabrerizo@outlook.es)


C++ Tutorial 1 Introducción POO.

10. Clases, estructuras y uniones en C++.

La clase y la estructura tienen prácticamente idénticas capacidades en C++. En C++, la


definición de una estructura se ha ampliado para que pueda también incluir funciones
miembro, incluyendo funciones constructoras y destructoras, de la misma manera que
puede hacerlo una clase. De hecho, la única diferencia entre una estructura y una clase
es que, por omisión, los miembros de una clase son privados y los miembros de una
estructura son públicos.

La sintaxis de una estructura en C++ es:


struct <nom_esctructura>
{
public:
<variables públicas>;
<métodos o funciones públicas>;
private:
<variables privadas>;
<métodos o funciones privadas>;
}lista de objetos;

De igual forma, en C++ las uniones y las clases también están relacionadas. En C++, una
unión también define un tipo de clase que puede contener como miembros tanto
funciones como variables. Una unión es como una estructura en la que, por omisión,
todos los miembros son públicos. Lo único que hay en una unión es que todos los
miembros comparten la misma posición de memoria (igual que en C). Las uniones
pueden contener funciones constructoras y destructoras.
Sin embargo, en C++ hay varias restricciones que aplicar a las uniones. No pueden
heredar ninguna otra clase y no se pueden usar como clases base por ningún otro tipo.
Las uniones no deben tener ningún miembro static. Además no pueden contener
ningún objeto que tenga un constructor o un destructor.

Francisco Javier Cabrerizo Membrilla (fjavier.cabrerizo@outlook.es) 19


C++. Tutorial 1 Introducción POO

11. Funciones insertadas.

En C++, es posible definir funciones a las que no se llama realmente, pero se insertan en
el código en el momento de cada llamada. Es casi igual que la forma en que trabaja una
macro con parámetros en C. La ventaja de las funciones insertadas es que no tienen
nada asociado con el mecanismo de llamada y vuelta de la función. Esto significa que
las funciones insertadas se pueden ejecutar más rápidamente que las funciones
normales.
La desventaja de las funciones insertadas es que si son demasiado largas y se las llama
demasiado a menudo, el programa aumentará su longitud de forma considerable.
Para declarar una función insertada, simplemente hay que preceder la definición de la
función con el especificador inline.
Ejemplo:

#include <iostream.h>
inline int area (int lado)
{
return (lado * lado);
}

int main()
{
cout << "Área = " area(5);
// equivalente a cout << "Área = " << (5*5);
return 0;
}

Una función insertada se tiene que definir antes de llamarla. Si no es así, el compilador
no tiene forma de saber que tiene que insertarla
Si por cualquier razón, el compilador no es capaz de cumplir la petición, la función se
compila como una función normal y la solicitud inline se ignora.

20 Francisco Javier Cabrerizo Membrilla (fjavier.cabrerizo@outlook.es)


C++ Tutorial 1 Introducción POO.

12. Inserción automática.

Si la definición de una función miembro es suficientemente corta, su definición se puede


incluir dentro de la declaración de clase. Hacer esto provoca que la función se convierta
automáticamente en una función insertada, siempre que sea posible. Cuando una
función se define dentro de una declaración de clase, la palabra clave inline no es
necesaria.
Ejemplo:
#include <iostream.h>
class cuadrado
{
private:
int l;
public:
cuadrado (int lado) {l = lado;}
int área() {return (l * l);}
int perímetro() {return (4 * l);}
};

Francisco Javier Cabrerizo Membrilla (fjavier.cabrerizo@outlook.es) 21


C++. Tutorial 1 Introducción POO

13. Asignación de objetos.

Un objeto se puede asignar a otro siempre y cuando ambos objetos sean del mismo
tipo. Por omisión, cuando un objeto se asigna a otro, se hace una copia a nivel de bits
de todos los miembros.
Ejemplo:
#include <iostream.h>
class ejemplo
{
private:
int a, b;
public:
intro (int i, int j);
visualiza();
};

ejemplo::intro (int i, int j)


{
a = i;
b = j;
}

ejemplo::visualiza()
{
cout << a << " " << b;
}
int main()
{
ejemplo o1, o2;
o1.intro(10,5);
o2.intro(20,15);
o2.visualiza();
o2=o1;
o2.visualiza();
return 0;
}

22 Francisco Javier Cabrerizo Membrilla (fjavier.cabrerizo@outlook.es)


C++ Tutorial 1 Introducción POO.

14. Paso de objetos a funciones.

Los objetos se pueden pasar a funciones como argumentos de la misma manera que se
pasan otros tipos de datos. Simplemente hay que declarar el parámetro como un tipo
clase y después usar un objeto de esa clase como un argumento cuando se llama a la
función. Igual que con otro tipo de datos, por omisión todos los objetos se pasan por
valor a una función.
Ejemplo:

#include <iostream.h>
class samp
{
private:
int i;
public:
samp (int n){i=n;}
void set_i (int n) {i=n;}
int get_i() {return i;}
};
void sqr_it(samp ob)
{
ob.set_i (ob.get_i() * ob.get_i());
cout << "La copia de ob tiene un valor i de " << ob.get_i();
}

int main()
{
samp o1(10);
sqr_it(o1);
cout << "pero o1.i no se cambia en main";
cout << o1.get_i(); return 0;
}

Francisco Javier Cabrerizo Membrilla (fjavier.cabrerizo@outlook.es) 23


C++. Tutorial 1 Introducción POO

15. Objetos devueltos por funciones.

Las funciones pueden devolver objetos, de igual forma que se pueden pasar objetos a
funciones. Para hacerlo, primero hay que declarar la función para que devuelva un tipo
de clase y segundo, hay que devolver un objeto de ese tipo usando la sentencia return.
Cuando un objeto es devuelto por una función, se crea automáticamente un objeto
temporal que guarda el valor devuelto. Este es el objeto que realmente devuelve la
función. Después de devolver el valor, este objeto se destruye. La destrucción de este
objeto temporal puede causar efectos laterales inesperados en algunas situaciones.
Este es el caso, al devolver objetos desde funciones si esos objetos contienen funciones
destructoras, porque el objeto devuelto sale fuera de ámbito tan pronto como el valor
se devuelve a la rutina de llamada.

24 Francisco Javier Cabrerizo Membrilla (fjavier.cabrerizo@outlook.es)


C++ Tutorial 1 Introducción POO.

16. Funciones amigas.

C++ soporta las funciones amigas. Una función amiga no es un miembro de una clase,
pero tiene acceso a sus elementos privados.
Una función amiga se define como una función no miembro normal. Sin embargo,
dentro de la declaración de clase para la que será una función amiga, está también
incluido su prototipo, precedido por la palabra clave friend.
Ejemplo:

#include <iostream.h>
class rectángulo
{
private:
int a, b;
public:
rectangulo (int ancho, int largo) {a = ancho; b = largo;}
int area() { return (a * b);}
int perimetro() { return (2 * (a + b));}
friend int volumen (rectángulo ob, int altura);
};
int volumen (rectángulo ob, int altura)
{
return (altura * ob.a * ob.b);
}

int main()
{
rectangulo rect(10,20);
cout << "Volumen: " << volumen (rect,5);
return 0;
}

Francisco Javier Cabrerizo Membrilla (fjavier.cabrerizo@outlook.es) 25


C++. Tutorial 1 Introducción POO

17. Arrays de objetos

Los objetos son variables y, por tanto, tienen las mismas capacidades y atributos que
cualquier otro tipo de variables. Por consiguiente, es perfectamente posible disponer
objetos en un array. La sintaxis para declarar un array de objetos es exactamente la
misma que la utilizada para declarar un array de cualquier otro tipo de variable. El
acceso a los array de objetos es igual al de los arrays de otros tipos de variables.

Ejemplo:

#include <iostream>
class cuadrado
{
private:
float lado;
public:
void intro_lado (float l) {lado=l;}
float area() {return lado*lado;}
float perimetro() {return 4*lado;}
};

int main()
{
cuadrado ob[4];
ob[1].intro_lado(5);
ob[2].intro_lado(10);
cout << "Área = " << ob[1].area();
cout << "Perimetro = " << ob[2].perimetro();
return 0;
}

Si un tipo de clase incluye un constructor, puede inicializarse un array de objetos de


dicha clase.
Ejemplo:

#include <iostream>
class cuadrado
{
private:
float lado;
public:
cuadrado (float l) {lado=l;}
float area() {return lado*lado;}
};
int main()
{
cuadrado ob[4] = {1, 5, 4, 10};
for (int i=0;i<4;i++)
cout << "Área = " << ob[i].area();
return 1;
}

26 Francisco Javier Cabrerizo Membrilla (fjavier.cabrerizo@outlook.es)


C++ Tutorial 1 Introducción POO.

Otra forma de inicializar arrays de objetos es mediante la forma extendida:


cuadrado ob[4] = {cuadrado(1), cuadrado(5), cuadrado(4),
cuadrado(10)};

También es posible crear arrays de objetos multidimensionales.

Ejemplo:
cuadrado ob[2][4] = {2, 3, 5, 7 4, 6, 9, 8};

Cuando se inicializa un array de objetos, cuyo constructor tiene más de un argumento,


debe utilizarse la forma de inicialización extendida mencionada anteriormente:

Ejemplo:
#include <iostream>
class Rectangulo
{
private:
int ancho, largo;
public:
Rectangulo (int a, int b) {largo=a; ancho=b;}
int area() {return ancho*largo;}
};

int main()
{
Rectangulo ob[4]= {ob(2,3), ob(2,4), ob(3,5), ob(4,5)};

for (int i=0;i<4;i++)


cout << "Área = " << obj[i].area();

return 0;
}

Francisco Javier Cabrerizo Membrilla (fjavier.cabrerizo@outlook.es) 27


C++. Tutorial 1 Introducción POO

18. Uso de punteros a objetos.

Como para cualquier otra variable se puede acceder a los objetos mediante punteros.
Cuando se utiliza un puntero a un objeto, las funciones miembro del objeto se
referencian utilizando el operador flecha (->) en lugar del operador punto (.).
La aritmética de puntero a un objeto es igual a la de cualquier otro tipo de datos.
Ejemplo:
#include <iostream>
class Samp
{
private:
int a, b;
public:
Samp (int n, int m){a = n; b = m;}
int get_a() {return a;}
int get_b() {return b;}
};

int main()
{
Samp ob[4] = {Samp(1, 2), Samp (3, 4), Samp (5, 6), Samp (7,8)};
int i;
Samp *p;
p = ob;
for (i=0; i<4; i++)
{
cout << p->get_a() << ' ';
cout << p->get_b() << "\n";
p++;
}
return 0;
}

28 Francisco Javier Cabrerizo Membrilla (fjavier.cabrerizo@outlook.es)


C++ Tutorial 1 Introducción POO.

19. El puntero "THIS".

C++ consta de un puntero especial llamado this. Este es un puntero que se pasa
automáticamente a cualquier miembro cuando se invoca. Es un puntero al objeto que
genera la llamada. Por ejemplo, dada la siguiente sentencia:
ob.f1(); // se entiende que ob es un objeto

la función f1() recibe automáticamente un puntero a ob, que es el objeto que genera la
llamada. Este puntero se referencia como this.
Es importante entender que sólo se pasa a los miembros punteros "this". Por ejemplo,
una función amiga no tiene puntero this.
Cuando se llama a un miembro se pasa automáticamente un puntero "this" al objeto
que provocó la llamada.
Ejemplo:
#include <iostream>
#include <string.h>
class Inventario
{
private:
char nombre[20];
double coste;
int existencias;
public:
Inventario (char *nom, double c, int e)
{
strcpy (nombre, nom);
coste = c;
existencias = e;
}
void ver();
};

void Inventario::ver()
{
cout << "nombre:" << this->nombre << "\n";
cout << "precio de coste: " << this->coste << "\n";
cout << "existencias: " << this->existencias << "\n";
}

int main()
{
Inventario ob("Llave ", 4.95, 4);
ob.ver();
return 0;
}

En este ejemplo no es necesaria la utilización explícita del puntero this.


El puntero this tiene varios usos, incluyendo la asistencia en la sobrecarga de
operadores.

Francisco Javier Cabrerizo Membrilla (fjavier.cabrerizo@outlook.es) 29


C++. Tutorial 1 Introducción POO

20. Asignación dinámica de memoria en C++.

C++ proporciona un método más conveniente y seguro para asignar y liberar memoria
que C. En C++, puede asignarse memoria utilizando new y liberarse mediante delete.
Estos operadores adoptan la siguiente forma general:
#include <iostream>
p_var=new <tipo>;
delete p_var;

En este caso, tipo es el especificador del tipo del objeto para el que se asigna memoria
y p_var es un puntero a este tipo. new es un operador que devuelve un puntero a la
memoria asignada dinámicamente. delete devuelve la memoria cuando ya no se
necesita.
Si no hay suficiente memoria disponible para atender la petición, new devuelve un
puntero nulo. Del mismo modo debe llamarse a delete sólo con un puntero obtenido
previamente mediante new. Si se llama a delete con un puntero incorrecto, se puede
bloquear el sistema.
Ejemplo:
#include <iostream>
main()
{
int *p; p = new int;
if (!p)
{
cout << "Error de asignación";
return 1;
}
*p = 1000;
cout << "El entero contenido en p es: " << *p << "\n";
delete p;
return 0;
}

30 Francisco Javier Cabrerizo Membrilla (fjavier.cabrerizo@outlook.es)


C++ Tutorial 1 Introducción POO.

Ejemplo:
#include <iostream>
class Ejemplo
{
private:
int i, j;
public:
void inicializa (int a, int b) {i = a; j = b;}
int producto() {return i * j;}
};

main()
{
Ejemplo *p;
p = new Ejemplo;
if (!p)
{
cout << "Error de asignación \n";
return 1;
}
p->inicializa(4,5);
cout << "El producto es: " << p->producto() << "\n";
delete p;
return 0;
}

Un objeto asignado dinámicamente puede tomar un valor inicial utilizando esta forma
de la sentencia new:
p_var = new <tipo> (valor inicial);

Para asignar dinámicamente un array unidimensional, debemos utilizar la siguiente


forma de new:
p_var = new <tipo> [tamaño];

Después de ejecutarse esta sentencia p_var apuntará a la primera posición de un array


de tamaño elementos del tipo especificado. Por diversas razones técnicas, no es posible
inicializar un array que ha sido asignado dinámicamente.

Para eliminar un array asignado dinámicamente, se utiliza la siguiente forma de delete:


delete[] p_var;

Francisco Javier Cabrerizo Membrilla (fjavier.cabrerizo@outlook.es) 31


C++. Tutorial 1 Introducción POO

Ejemplo:
#include <iostream>
class Ejemplo
{
private:
int i, j;
public:
void inicializa (int a, int b) {i = a; j = b;}
~Ejemplo() {cout << "Destrucción ...\n";}
int producto() {return (i * j);}
};

main()
{
Ejemplo *p;
int cont;
p = new Ejemplo[10]; // Asignación dinámica de un array de objetos
if (!p)
{
cout << "Error de asignación \n";
return 1;
}
for (cont = 0; cont < 10; cont ++)
p[cont].inicializa(cont, cont);
for (cont = 0; cont < 10; cont ++)
{
cout << "Producto [" << cont << "] es: ";
cout << p[cont].producto() << "\n";
}
delete[] p;
return 0;
}

32 Francisco Javier Cabrerizo Membrilla (fjavier.cabrerizo@outlook.es)


C++ Tutorial 1 Introducción POO.

21. Referencias.

Una referencia es un puntero implícito que, a todos los efectos, se comporta como
cualquier otro nombre para una variable. Existen tres modos de utilizar una referencia:
1. Una referencia puede pasarse a una función.
2. Una referencia puede ser devuelta por una función.
3. Pueden crearse referencias independientes.
El uso más importante de una referencia es como parámetro de una función.

Ejemplo: Paso de un argumento por referencia utilizando un puntero como parámetro.


#include <iostream>
void f(int *n);

main()
{
int i = 0;
f(&i);
cout << "Este es el nuevo valor de i " << i << "\n";
return 0;
}

void f(int *n)


{
*n = 100;
}

En un programa C, ésta es la única manera de realizar una llamada por referencia. Sin
embargo, en C++ puede automatizarse completamente este proceso utilizando un
parámetro por referencia, de la siguiente manera:
#include <iostream>
void f(int &n);
main()
{
int i = 0;
f(i);
cout << "Este es el valor de i: " << i << "\n";
return 0;
}

void f(int &n)


{
n = 100;
}

Para declarar una variable o parámetro por referencia el nombre de la variable debe ir
precedido por &. Cuando una variable (n en el ejemplo anterior) se declara como una
referencia, ya no es necesario, e incluso es erróneo, aplicar el operador *. En su lugar,
cada vez que se utiliza n dentro de la función f() automáticamente es considerada como
un puntero al argumento utilizado para llamar a la función.

Francisco Javier Cabrerizo Membrilla (fjavier.cabrerizo@outlook.es) 33


C++. Tutorial 1 Introducción POO

Cuando se utiliza un parámetro por referencia, el compilador pasa automáticamente


como argumento la dirección de la variable utilizada. No es necesario y de hecho no
está permitido generar a mano la dirección del argumento precedido del &. Además,
dentro de la función, el compilador usa automáticamente la variable apuntada por el
parámetro de referencia. No se requiere y de nuevo no está permitido usar el *.
Ejemplo: Función que utiliza referencias:
void intercambia (int *x, int *y)
{
int t;
t = *x;
*x = *y;
*y = t;
}

void intercambia (int & x, int & y)


{
int t;
t = x;
x = y;
y = t;
}

main()
{
int a=5, b=10;
cout << "El valor de a es: " << a << "\n";
cout << "El valor de b es: " << b << "\n";
intercambia(5,10);
cout << "El nuevo valor de a es: " << a << "\n";
cout << "El nuevo valor de b es: " << b << "\n";
return 0;
}

21.1. Paso de referencias a objetos.


Cuando se pasa un objeto a una función, mediante el uso del mecanismo implícito del
paso de parámetros por valor, se hace una copia del objeto. Aunque no se llame a la
función constructora del parámetro, cuando finaliza se llama a su función destructora.
Esto podía ocasionar efectos laterales.
Una solución a este problema es el paso de un objeto por referencia. Cuando se pasa el
objeto por referencia no se hace copia alguna y, por consiguiente, no se llama a su
función destructora cuando la función finaliza.
Es muy importante entender que una referencia no es un puntero. Por tanto, cuando se
pasa un objeto por referencia, el operador de acceso a un atributo utiliza el punto (.) y
no la flecha (->).

34 Francisco Javier Cabrerizo Membrilla (fjavier.cabrerizo@outlook.es)


C++ Tutorial 1 Introducción POO.

Ejemplo: Paso de un objeto por valor.

#include <iostream>
class Miclase
{
private:
int x;
public:
Miclase (int n)
{
x = n;
cout << "Construcción " << x << "\n";
}
~Miclase () {cout << "Destrucción " << x <<"\n";}
int id() {return x;}
};

void f(Miclase o)
{
cout << "Recibido " << o.id() << "\n";
}
main()
{
Miclase x(1);
f(x);
return 0;
}

Ejemplo: Paso de un objeto por referencia utilizando referencias.


#include <iostream.h>
class Miclase
{
private:
int x;
public:
Miclase (int n)
{
x = n;
cout << "Construcción " << x << "\n";
}
~Miclase () {cout << "Destrucción " << x <<"\n";}
int id() {return x;}
};
void f(Miclase &o)
{
cout << "Recibido “ << o.id() << "\n";
}
main()
{
Miclase x(1);
f(x);
return 0;
}

Francisco Javier Cabrerizo Membrilla (fjavier.cabrerizo@outlook.es) 35


C++. Tutorial 1 Introducción POO

21.2. Devolución de referencias.


Otro aspecto interesante de las referencias es que una función puede devolver una
referencia. La devolución de una referencia puede ser muy útil cuando se sobrecargan
determinados tipos de operadores. Sin embargo, también puede usarse para utilizar una
función en el lado izquierdo de una sentencia de asignación.

Ejemplo:
#include <iostream>
int &f();
int x;

main()
{
f() = 100;
cout << x << "\n";
return 0;
}

int &f()
{
return x;
}

La función f() devuelve una referencia. Por tanto, cuando f() se utiliza en el lado
izquierdo de una sentencia de asignación, la asignación se producirá sobre la referencia
devuelta por f(). Puesto que f() devuelve una referencia a x, es x la que recibe el valor
100.
Como es sabido, en C y en C++ no se comprueban los límites del array. Por consiguiente,
es posible sobrepasar o no alcanzar los límites del mismo. Sin embargo, en C++, puede
crearse una clase array que realice automáticamente la comprobación de los límites. La
clase array contiene dos funciones esenciales: una que almacena la información dentro
del array y otra que la recupera. Estas funciones pueden comprobar en tiempo de
ejecución, que no se sobrepasan los límites del array.

36 Francisco Javier Cabrerizo Membrilla (fjavier.cabrerizo@outlook.es)


C++ Tutorial 1 Introducción POO.

El siguiente programa construye un array de comprobación de límites para caracteres:


#include <iostream>
#include <stdlib.h>

class Array
{
private:
int size;
char *p;
public:
Array (int num);
char &put (int i);
char get (int i);
};
Array::Array (int num)
{
p = new char [num];
if (!p)
{
cout << "Error de asignación";
exit (1);
}
size = num;
}
// Almacena la información dentro del array.
char &Array::put (int i)
{
if (i < 0 || i >= size)
{
cout << "Error en límites";
exit (1);
}
return p[i];
}
// Extrae información del array.
char Array::get(int i)
{
if (i < 0 || i >= size)
{
cout << "Error en límites";
exit (1);
}
return p[i];
}
main()
{
Array a(10);
a.put (3) = 'x';
a.put (2) = 'R';
cout << a.get(3) << a.get(2) << "\n";
a.put (11) = ‘g’; //Error de límites
return 0;
}

Francisco Javier Cabrerizo Membrilla (fjavier.cabrerizo@outlook.es) 37


C++. Tutorial 1 Introducción POO

21.3. Referencias independientes.


Aunque no se utiliza frecuentemente, es posible crear una referencia independiente.
Esta es una variable de referencia que, a todos los efectos, es simplemente otro nombre
para otra variable. Debido a que no puede asignarse menos valores a las referencias,
una referencia independiente debe inicializarse cuando se declara. En la medida de lo
posible, debería evitarse su uso.
Ejemplo:
#include <iostream>
main()
{
int x;
int &ref = x; // Creación de una referencia independiente
x = 10; // estas dos sentencias
ref = 10; // son funcionalmente equivalentes
ref = 100;
cout << x << "\n";
return 0;
}

38 Francisco Javier Cabrerizo Membrilla (fjavier.cabrerizo@outlook.es)

También podría gustarte