Tutorial Profr. Rogelio Cesar
Transcript of Tutorial Profr. Rogelio Cesar
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 1/212
Tutorial de programacion, tentativament llamado:
El lenguaje de
programacion C++por
Rogelio Cesar Rodriguez Cervantes
(c) copyright 2008-2012, por Rogelio Cesar Rodriguez Cervantes
Esta version es una edicion temprana aun en desarrollo, para
cualquier comentario y/o sugerencia este es mi email:
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 1
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 2/212
CONTENIDO
Prefacio iv
Capítulo 1 Fundamentos del lenguaje………………………….……… 1
1.1 Introducción al lenguaje y a su entorno de desarrollo……..…. 11.2 Comentarios.………….………………………….……………..… 51.3 Variables y constantes.………….………………………………. 81.4 Objetos que permiten E/S por consola.………….…………….. 151.5 Operadores…………………………………..………..………….. 171.6 Tipos de datos.……………………………….…………….…….. 21
1.6.1 Fundamentales…………………….…………………… 211.6.2 Definidos por el usuario..………….………………….. 27
1.7 Palabras reservadas…….…………………….…………………. 331.8 Expresiones………………………………………..……………… 351.9 Estructuras de control…………………….…………………….... 35
1.9.1 Asignación…………………….………………………… 361.9.2 Selección…………………….…………………..…….... 36
1.9.3 Iteración…………………….…………………………… 51Capítulo 2 Subprogramas………………………………………………... 58
2.1 Definición de un subprograma…………………….……………. 582.1.1 Estructura de un subprograma……………………..… 592.1.2 Valor de retorno…………………….………………….. 60
2.2 Declaración de un subprograma…………………….………..… 622.3 Bibliotecas o librería de subprogramas…………………….….. 632.4 Primer acercamiento a clases y objetos……………………… 672.5 Ámbito y tiempo de vida de variables…………………….……. 692.6 Argumentos y paso de parámetros…………………….………. 732.7 Sobrecarga de subprogramas…………………….……………. 772.8 Recursividad….…………….…………………..……….……….. 78
Capítulo 3 Punteros, referencias y arreglos………………………….. 823.1 Creación………………………..………………………………….. 823.2 Operaciones con punteros………………………..……………... 853.3 Referencias…………………….………….……………………… 913.4 Arreglos unidimensionales, bidimensionales y multidimensionales.. 943.5 Cadenas de caracteres…………………….……………...…….. 1063.6 Asignación dinámica de memoria…………………….………… 1163.7 Uso de clases predefinidas para arreglos……………………... 129
Capítulo 4 Clases y Objetos…………………………………………….. 1324.1 Definición de una clase…………………….……………………. 1324.2 Declaración de clases…………………….…………………..…. 1324.3 Miembros de una clase…………………….……………………. 1334.4 Ámbito referente a una clase…………………….……………… 133
4.5 Especificadores de acceso…………………….………………... 1344.6 Creación de objetos…………………….…………………..……. 1354.7 Puntero this…………………….…………………..………….….. 1384.8 Constructores y destructores...…………………..……………... 142
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 2
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 3/212
Capítulo 5 Herencia……………………………………………………….. 1565.1 Importancia de la herencia en la POO…………………….…… 1565.2 Jerarquía de herencia…………………….…………………..…. 156
5.2.1 Conceptos de herencia simple y múltiple…………… 1575.2.2 Principios generales de diseño de jerarquías………. 1585.2.3 Especificadores de acceso a jerarquía de clases…... 159
5.3 Definición de una clase base…………………….……………… 1605.4 Definición de una clase derivada…………………….…………. 165
5.4.1 Constructores y destructores de clases derivadas…. 1665.4.2 Conversión implícita de objetos de clase derivada a
objeto de clase base……………..…………………….. 1665.5 Herencia múltiple…………………….………………………….... 173
Capítulo 6 Polimorfismo……………………………………………...….. 1796.1 Concepto de polimorfismo…………………….………………… 1796.2 Clase base abstracta…………………….…………………..….. 1826.3 Subprogramas virtuales…………………….…………………… 1866.4 Destructores virtuales…………………….…………………..…. 190
Capítulo 7 Archivos……………………………………………………….. 1937.1 Clases de E/S Clase base abstracta…………………….……... 1937.2 Realizar entrada y salida de texto…………………….………… 1947.3 Leer y escribir archivos…………………….…………………..… 1947.4 Realizar entrada y salida binaria…………………….………….. 203
Bibliografía……………………………………………………………………. 209
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 3
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 4/212
Prefacio
Se intenta que cada programa de ejemplo sea una aplicación completa y
práctica en la medida que el conocimiento adquirido hasta ese punto lo permita,
sin que llegue a ser compleja. También se ha tratado de evitar en todo lo posible
el tipo de escritura compacta tradicional de los programas en C/C++ para lograr
mayor claridad en los ejemplos.
Cuando la presentación de los programas de ejemplo lo permite (no interfiere
con la explicación) siguen una notación de anteponer la(s) primera(s) letras de
los tipos de datos usados, basada un poco en la notación húngara.
Versión de C++
El material presentado aquí, sigue el estándar de programación de C++ ISO/IEC
98-14882, por lo tanto los ejemplos podrán ser compilados con cualquier
compilador que sigua el estándar ISO Internacional así como el ANSI de
Estados Unidos.
Los programas de ejemplo fueron compilados con “Visual C++ 2008 Express
Edition” en el sistema operativo Windows XP y con el compilador “GNU de C/C++” en el sistema operativo Linux.
“Que sea sencillo: lo mas sencillo posible, pero no mas”- Albert Einstein
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 4
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 5/212
Capitulo 1
Fundamentos del lenguaje
1.1 Introducción al lenguaje y a su entorno de
desarrollo.
El lenguaje de programación C++ fue desarrollado por Bjarne Stroustrup en los
laboratorios BELL en 1983, originalmente Stroustup lo llamo “C con clases” al
ser C++ un súper conjunto del lenguaje C; C++ trata de seguir la eficiencia, la
rapidez de ejecución y la libertad de programación de C con la inclusión de lastécnicas de programación del modelo orientado a objetos; pero a diferencia de
otros lenguaje orientados a objetos, C++ sigue el espíritu original del lenguaje C,
donde el uso de esas técnicas depende del programador, así que al igual que en
C; en C++ el programador tiene la última palabra.
Lo mejor de C++ es que permite muchas formas de codificar programas, los
paradigmas de programación más comunes y que el C++ soporta fácilmente son
(Stroustrup 1997):
1. Programación estructurada
2. Programación modular
3. Abstracción de datos
4. Programación orientada a objetos
5. Programación genérica
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 5
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 6/212
El lenguaje C es parte del lenguaje C++, la mayoría de las instrucciones de C
funcionan en C++, y existen muchas instrucciones equivalentes, en estos casos
se ha utilizado las instrucciones de C++ y dejado afuera las de C. Esto no quiere
decir que las del Lenguaje C no sean útiles, la capacidad de discernir cuales
utilizar en cada caso se obtendrá conforme se domine el lenguaje.
Los programas de ejemplo siguen la notación de anteponer la(s) primera(s)
letras de los tipos de datos usados, basada un poco en la notación húngara.
Para evitar complejidad innecesaria algunos programas de ejemplo no siguen tal
notación.
En C++ el entorno de desarrollo no esta ligado a un solo programa hecho por
una sola compañía como en el caso del lenguaje de programación Visual Basic
de Microsoft. Siendo C++ un lenguaje estándar, el entorno de desarrollo
depende de la selección de entre una variedad de ofertas, así como del sistema
operativo que se este utilizando. Independientemente del entorno de desarrollo
utilizado, la creación de programas usando el lenguaje C++ sigue un proceso
como se muestra en la figura de la siguiente pagina.
fig1. Diagrama del proceso de creación de un programa ejecutable usando el lenguaje C++
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 6
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 7/212
Editor
Un programa usado para escribir el texto del lenguaje, este texto es sin formato.
Compilador
Programa que checa que el lenguaje sea usado correctamente y lo traduce a un
lenguaje objeto cercano a lenguaje máquina.
Encadenador
Programa que toma programas compilados separadamente y los une en un
lenguaje de maquina, los deja listo para ejecutarse.
Lenguaje Maquina Instrucciones que la computadora entiende directamente.
El proceso llamado preprocesador, compilador y el de encadenador se realizan
generalmente invocando un solo programa, por ejemplo en una terminal de
Linux usando:
g++ programa.cpp
g++ realiza los tres procesos y deja un programa ejecutable, llamado por
omisión "a.out".En el caso de Windows, en la ventana de comandos utilizando borland C++ por
ejemplo es como sigue:
bcc programa.cpp
Dando como salida el programa ejecutable llamado por omisión igual que el de
entrada pero con la extensión “exe”, en este caso "programa.exe".
A estos programas g++ y bcc se les llama por el termino general de "compilador"
aunque realicen mas cosas que la compilación (generalmente estos programas
mandan llamar otros programas que realizan cada uno un proceso mostrado en
la figura de arriba), además estos compiladores cuentan con opciones para que
solo se ejecute uno de los procesos arriba mencionados porque en ocasiones es
útil hacerlo de esa manera.
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 7
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 8/212
La selección de un entorno de desarrollo para C++ depende en gran parte de las
necesidades particulares de cada programador, la plataforma de desarrollo y/o la
imposición de este por parte de un empleador, por ejemplo.
El entorno de desarrollo puede ser tan escueto como utilizar un editor de texto y
un compilador o tan basto como el uso de un entrono de desarrollo integrado,
por ejemplo Microsoft Visual C++ en el caso de Windows y Eclipse con el plugin
CDT en Windows/Linux.
fig2. Entorno integrado de desarrollo de Microsoft Visual C++ Express Edition
fig3. Entorno integrado de desarrollo de Eclipse con el plugin CDT
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 8
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 9/212
1.2 Comentarios
Dos diagonales seguidas indican el inicio de un comentario; las diagonales
deben estar pegadas sin espacios intermedio.
// Primer.cpp// Escribe un mensaje en pantalla
Todo lo que esta después de estos caracteres hasta el fin de la línea es
ignorado por el compilador, se utilizan para poner notas para el programador.
También se pueden utilizar los caracteres /* */ para poner comentarios, estos
son los usados por el lenguaje C, la ventaja de estos es que pueden ser
utilizados para crear bloques de varias líneas, por ejemplo los comentariosanteriores pueden ser línea por línea:
/* Primer.cpp */
/* Escribe un mensaje en pantalla */
O pueden enmarcar varias líneas:
/* Primer.cpp
Escribe un mensaje en pantalla */
Los caracteres, diagonal y asterisco deben de ir pegados.
El primer programa en C++, el siguiente ejemplo muestra un pequeño
programa, que despliega un mensaje en la pantalla, utilizando el objeto “cout”
para realizar salida a la consola.
Listado// Primer.cpp
// Escribe un mensaje en pantalla
#include <iostream>
using namespace std;
int main()
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 9
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 10/212
{
cout << "Este es mi primer programa en C++";
return 0;
}
Salida
Este es mi primer programa en C++
Nota:
El C++ hace distinción entre minúsculas y mayúsculas, por ejemplo: La palabra
Main, es diferente de mAin, o main que es la que reconoce C++.
Aunque el programa de ejemplo anterior es bastante pequeño, este incluye
elementos clave que conforman la mayoría de los programas en C++.
// Primer.cpp
// Escribe un mensaje en pantalla
Es recomendado incluir como comentarios al inicio de cada programa fuente el
nombre del programa así como una breve descripción de lo que hace.
#include <iostream>
#include se utiliza para especificar la inclusión de un archivo de texto, el nombre
del archivo se pone entre los símbolos menor que y mayor que. En este caso el
nombre del archivo de texto es iostream el cual contiene definiciones para
realizar entrada y salida de datos –por ejemplo leer del teclado y desplegar en
pantalla- entre otras cosas.
using namespace std;
Se asocia, el “namespace std” para todo el programa e indica que el programa
va a utilizar el conjunto de variables globales definidos en el espacio de nombres
estándar.
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 10
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 11/212
Los espacios entre las palabras se utilizan para separar las instrucciones, las
líneas en blanco son ignoradas por el compilador y se utilizan para darle
legibilidad al código.
int main()
main indica donde empieza la ejecución del programa, int es un tipo de datos
(esto se discute mas adelante) e indica el tipo de valor que el programa va a
regresar al proceso que lo ejecute.
{
La llave que abre indica que inicia la ejecución de un bloque de código
}
La llave que cierra termina el bloque y ambas “{“ y “}” enmarcan el código que
integra la función.
cout << "Este es mi primer programa en C++";
Imprime en la consola lo que esta entre comillas "Este es mi primer programa en
C++".
return 0;
“return” regresa el valor indicado al proceso que lo mando llamar, en este caso
un cero y probablemente al Sistema Operativo.
Nota:
Si esta usando el Sistema Operativo Windows y un IDE (Integrated DevelopmentEnvironment/Entorno de Desarrollo Integrado) como por ejemplo Visual C++ o
Dev-C++, puede detener la ejecución del programa para evitar que se cierre la
ventana de comandos (msdos), utilizando:
system("PAUSE > NUL");
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 11
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 12/212
De lo contrario al terminar la ejecución regrese al IDE como si no hubiera
realizado nada el programa.
Nota (continua de la página anterior):
#include <iostream>
using namespace std;
int main()
{
cout << "Este es mi primer programa en C++";
//para pasusa si se ejecuta en un IDE como dev-c++ o vc++ por ej.
system("PAUSE > NUL");
return 0;
}
system() Es una función que permite ejecutar comandos externos. PAUSE es un
comando batch –del msdos- para detener la ejecución de un script, la sentencia:
PAUSE > NUL redireccióna la salida del comando PAUSE a nulo, -la salida de
este comando es un mensaje.
Los programas de ejemplo no incluyen tal sentencia porque un Entorno de
Desarrollo Integrado solo se utiliza cuando se esta desarrollando el programa,
cuando el programa (o programas según sea el caso) esta terminado, este se
ejecuta fuera del Entorno de Desarrollo Integrado, por lo tanto tal sentencia
dejaría de ser útil o peor, entorpecería la función del programa terminado.
1.3 Variables y constantes
Las variables son lugares de almacenamiento al cual se le asigna un nombre
para poder accesar y manipular lo que se guarda en ese lugar.
Declaración de variables
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 12
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 13/212
Una declaración especifica un tipo y le sigue una lista de una o más variables de
ese tipo. Todas las variables deben de ser declaradas antes de utilizarlas.
Ejemplo:
int a, b;
char c;
Al declarar una variable también se le pude asignar un valor.
Ejemplo:
int i = 0;
float x = 3.4;
Listado// variables.cpp
// Declaracion de variables
#include <iostream>
using namespace std;
int main() {
int n, c;
c = 2;n = c * c;
cout << "El cuadrado de 2 es " << n;
return 0;
}
Salida
El cuadrado de 2 es 4
Nota:
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 13
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 14/212
Un programa es perfectamente legal para el compilador si se escribe en una
sola línea, por Ejemplo:
int main() { cout << "Hola"; return 0; }
Nota (continua de la página anterior):
Escribir los programas en varias líneas y con la sangría adecuada mejora la
legibilidad de los mismos, algo trivial en programas pequeños pero de de suma
importancia en programas “reales” donde el numero de líneas suman docenas si
no es que cientos (Miles en ocasiones).
Los programas de ejemplo de aquí en adelante llevan la llave que abre “{“ en la
misma línea del “main()” principalmente para ahorrar una línea de espacio y
mostrar mas líneas de código en una pantalla de edición, sin sacrificar legibilidadya que el “int main() “ indica claramente el inicio del programa (y el nombre de la
función, estructura, etc., en los ejemplos posteriores).
Ejercicios
Declare una variable para cada inciso que pueda ser usada para almacenar el
valor mencionado
a) 3.1416
b) -554
c) 30000
d) Resultado de 10 * 3
e) Resultado de 10/3
f) 'a'
g) "a"
h) "HOLA"
i) Resultado de 'a' + 'b' j) Resultado de "a" + "b"
Constantes
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 14
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 15/212
Son los valores fijos que el programa no puede alterar, en C++ las constantes
tienen un tipo de dato (ver tipos de datos mas adelante) por ejemplo las
constantes de carácter, las cuales se encierran entre apóstrofes.
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 15
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 16/212
Ejemplo:
'a', '%'
Distíngase que son diferentes:
'a' y "a"
'a' es una constante de carácter compuesta por la letra a y "a" es una cadena de
caracteres compuesta por la letra a y el carácter nulo y esta formada de dos
elementos.
"" es una cadena nula con un elemento (\0).
Ejemplo:
123L constante long
123.3 constante float
Un cero que encabeza un número significa octal
Ejemplo:
011 9 en decimal
Un cero y una equis antes significa hexadecimal.
Ejemplo:0xFF 255 en hexadecimal.
Constantes de carácter no imprimibles
Código Significado\b Retroceso\f Alimentación de hoja\n Nueva línea\r Retorno de carro\t Tabulador horizontal\” Doble comilla\’ Comilla simple\0 Nulo\\ Barra invertida\v Tabulador vertical\a Alerta
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 16
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 17/212
\o Constante octal\x Constante hexadecimal
Una constante de carácter no imprimible no tiene una representación gráfica
solo realiza una acción.Ejemplo:
cout << “\n”;
No imprime nada, solo brinca de línea, es como si presionáramos la tecla
ENTER/RETORNO. Los dos caracteres “\n” son interpretados como un
solo carácter.
Ejemplo:
Para desplegar un mensaje con una parte entre comillas por ejemplo:
Referencia: “C++ Simplificado”-pagina 123, se necesita utilizar el
carácter no imprimible \”
cout << ”Referencia: \”C++ Simplificado\”-pagina 123”;
Si no se antepone la diagonal invertida a las comillas el string termina enlas segundas comillas y las terceras comillas producirían un error.
Listado
// caracter.cpp
// Formato de texto en la salida estándar
// utilizando las constantes de carácter no imprimibles
#include <iostream>
using namespace std;
int main(){
cout << "CARACTERES\t\t";
cout << "NO IMPRIMIBLES";
cout << endl << "Esta linea esta en otro renglon";
cout << "\n\n\n\n\nEsta despues de cuatro renglones";
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 17
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 18/212
return 0;
}
Salida CARACTERES NO IMPRIMIBLES
Esta linea esta en otro renglón
Esta despues de cuatro renglones
cout << "CARACTERES\t\t";
La secuencia de caracteres “\t”, indica imprimir un TAB, es como si se
presionara la tecla TAB.
cout << endl << "Esta linea esta en otro renglon";
La palabra “endl” después de los caracteres “<<” indica un salto de línea antes
de imprimir el mensaje.
cout << "\n\n\n\n\nEsta despues de cuatro renglones";
El “endl” se utiliza para cambiar al siguiente renglón, pero en ocasiones es mas
practico usar el carácter no imprimible “\n”.
Ejercicio
Escriba un programa que imprima sus datos personales centrados lo más
posible en pantalla, utilizando las constantes de carácter no imprimibles.
Constantes simbólicas
#define
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 18
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 19/212
Mediante esta construcción al principio de un programa se puede definir un
nombre simbólico o constante simbólica como una determinada cadena de
caracteres.
Listado
// pascual.cpp
// Emulacion del PASCAL mediante el preprocesador
#include <iostream>
using namespace std;
#define PROGRAM int main()
#define BEGIN {
#define END return 0; }
#define WRITE(A) cout << A
PROGRAM
BEGIN
WRITE("Pascal en C++!!!");
END
Salida
Pascal en C++!!!
El preprocesador remplaza todas las apariciones no entre comillas del nombre
por su cadena correspondiente.
Ejercicio
Investigue todas las palabras reservadas del preprocesador, su sintaxis y un
ejemplo de cada una.
Constantes con nombre
Para crear una constante con nombre se utiliza la palabra reservada “const ” al
declarar un objeto.
Ejemplo:
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 19
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 20/212
const int numero_constante = 10;
const char caracter_constante = ‘X’;
A las constantes no se les puede asignar valores después de creadas así que se
les asigna al momento de declararlas.
1.4 Objetos que permiten E/S por consola
El lenguaje C++ cuenta con una biblioteca estándar de objetos predefinidos para
realizar diversas actividades, entre estos objetos se encuentran el "cin" y el
"cout" para realizar entrada y salida por la consola.
Objeto cout
“cout” es el nombre de un objeto que representa la salida estándar a la consola
(Console output/Salida en la consola).
Ejemplo:
cout << "Este es mi primer programa en C++";
Imprime en la salida estándar lo que esta entre comillas "Este es mi primer
programa en C++".
Los caracteres << son para simular una flecha la cual indica que lo que sigue va
para la salida estándar.
Un mensaje en cada línea, para controlar el cambio de línea se manda imprimir
la palabra “endl”, que es un acrónimo de end line –fin de línea-.
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 20
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 21/212
Listado
// control.cpp
// utilización del objeto cout con el endl
#include <iostream>
using namespace std;int main() {
cout << "Ahora vamos a controlar" << endl;
cout << "el cambio de linea ";
cout << "para dominar" << endl << "los mensajes";
cout << endl << endl << endl << "Y DESPUES EL C++...";
return 0;
}
Salida
Ahora vamos a controlar
el cambio de linea para dominar
los mensajes
Y DESPUES EL C++...";
cout << "Ahora vamos a controlar" << endl;
La palabra endl después de los caracteres << indica un salto de línea después
de imprimir el mensaje.
cout << "para dominar" << endl << "los mensajes";
cout << endl << endl << endl << "Y DESPUES EL C++...";
El endl se puede incluir en cualquier parte después de los caracteres << y tantas
veces como sea necesario.
Nota:
Las siguientes líneas producen la misma salida:
cout << “Hola a todos”;
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 21
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 22/212
cout << “Hola” << “ a “ << “todos”;
Objeto cin
“cin” es un el nombre de un objeto que representa la entrada estándar (Console
INput/Entrada en la consola), por omisión el teclado de una computadora.Ejemplo:
cin >> fDolares
Ingresa una entrada de datos de la entrada estándar y lo almacena en la
variable fDolares.
Los caracteres >> son para simular una flecha la cual indica que lo que sigue va
de la entrada estándar hacia una variable.
El objeto “cin”, como la mayoría de los objetos cuenta con métodos (Se estudian
en el siguiente capítulo) que se pueden llamar.
Ejemplo:
cout << “Presione ENTER para continuar”;
// Ignora el ultimo ENTER leído, que puede estar en el buffer de entrada
cin.ignore(1, '\n');
cin.get(); // espera por un ENTER
El código anterior detiene la ejecución hasta que el usuario presione la tecla
ENTER.
1.5 Operadores
Lo operadores son utilizados para realizar operaciones matemáticas, lógicas y/o
de relación.
Operadores aritméticos
Operador Acción- Resta y menos unario+ Suma
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 22
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 23/212
* Multiplicación/ División
% Modulo de división-- Decremento en uno++ Incremento en uno+= Incremento y asignación-= Resta y asignación*= Multiplicación y
asignación/= División y asignación
Operadores ++ y --
Lo mas común al utilizar estos operadores es aplicarlos dentro de una sentencia
de una sola variable, en este caso no importa el orden del operador, ya sea en
forma prefija o pos fija actúan de la misma manera, incrementa o decrementa en
uno según sea el caso.
Ejemplo:
i++;
Es equivalente a:
i = i + 1;
Prefijo y posfijo de los operadores ++, --
Los operadores ++ y – actúan diferente dependiendo de la forma en que se
usen, prefija o postfija
Ejemplo:
n = i++;
Es equivalente a:
n = i;
i = i +1;
n = ++i;
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 23
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 24/212
Es equivalente a:
i = i +1;
n = i;
Al usar la forma de prefijo la variable se incrementa o decrementa antes de ser
usada; en la forma pos fijo la variable primero se usa y después se incrementa o
decrementa según sea el caso.
Listado
// mas_mas.cpp
// Desmostracion del operador unario ++
#include <iostream>
using namespace std;
int main() {
int i;
i = 10;
i++;
cout << "i = " << i;
cout << "\nSalida en posfija de i++ = " << i++;
cout << "\n\nSalida de i = " << i;
cout << "\nSalida prefija de ++i = " << ++i;
return 0;
}
Salida
i = 11
Salida en posfija de i++ = 11
Salida de i = 12
Salida prefija de ++i = 13
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 24
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 25/212
Operadores relacionales
Operador Acción
> mayor que
>= mayor que o igual que< menor que
<= menor que o igual que== Igual!= no igual
Nota:
El doble signo igual == es la notación de C++ para "es igual a". Este símbolo se
distingue de la condición de igualdad del simple = empleado en las
asignaciones.
Operadores lógicos
Operador Acción
&& and|| or! not
Precedencia y orden de evaluación de operadores
Existen reglas de precedencia y orden de evaluación de operadores para
cuando estos se mezclan en una misma sentencia.
Operador Asociatividad() [] -> . Izquierda a derecha
! ~ ++ -- - * & sizeof Derecha a izquierda* / % Izquierda a derecha+ - Izquierda a derecha
<< >> Izquierda a derecha< <= > >= Izquierda a derecha
== != Izquierda a derecha& Izquierda a derecha
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 25
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 26/212
^ Izquierda a derecha| Izquierda a derecha
&& Izquierda a derecha|| Izquierda a derecha?: Derecha a izquierda
= += -= *= /= Izquierda a derecha, Derecha a izquierda
1.6 Tipos de datos
Los tipos de datos sirven para declarar lugares de almacenamiento durante la
ejecución del programa, dependiendo del tipo de dato utilizado es lo que
podemos almacenar.
1.6.1 Tipos de datos fundamentales
Los tipos básicos y más usados en un programa de C++ son:
Tipo Se utiliza para
almacenar
Descripción
char caracteres Un tipo de dato específico para manejo de
caracteres de 8 bits de rango igual a -128 a
127.int enteros Tipo de dato entero con signo de 16, 32 ó
64 bits, dependiendo del compilador. En
sistemas de 16 bits su rango de valores es
de -32763 a 32762. Para sistemas de 32
bits el rango se de -2147483648 a
2147483647. En sistemas de 64 bits el
rango será de 1.7+/-308.long enteros largosfloat flotante, número con
fracción
Número real de 32 bits cuyo rango vá de
3.4+/-38. Generalmente su precisión es de
7 dígitos.
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 26
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 27/212
double flotante, número con
fracción
Número de 64 bits y de rango igual a 1.7+/-
308 con una precisión en general de 15
dígitos.void indica que nada o
indefinido
Nota:
Para saber exactamente cuantos bytes están disponibles para un determinado
tipo de dato en el compilador que se este usando, se puede usar la función
sizeof.
Ejemplo:
cout << sizeof(char);
Imprime el número de bytes usados por el tipo de datos char.+
Listado
// condolar.cpp
// Demuestra la declaración de variables
// así como la entrada y salida de datos
// Convierte dolares a pesos
#include <iostream>
using namespace std;
int main(){
float iPesos, fDolares;
cout << endl << "Cuantos dolares desea convertir a pesos? ";
cin >> fDolares;
iPesos = fDolares * 12.5;
cout << "Pesos = " << iPesos;
return 0;
}
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 27
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 28/212
Salida en base a la entrada de ejemplo
Cuantos dolares desea convertir a pesos? 9
Pesos = 112.5
float iPesos, fDolares;
Se declaran dos variables de tipo punto flotante, para almacenar números con
parte fraccionaria, números como 3.1416, 2.5 y 1234, este último es un número
entero pero es almacenado como 1234.00.
Nota:
También se puede declarar cada variable en una línea separada:
float iPesos;
float fDolares;
Para guardar un número entero; números sin parte faccionaria como 5, 100 y 15
pero no 3.14 seria:
int pesos;
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 28
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 29/212
Ejercicios
1. Modifique el programa condolar.cpp, para que pida el tipo de cambio.
2. Realice un programa que calcule el área de un triángulo.
3. Escriba un programa que calcule el área de un cuadrado.
Modificadores de tipo
Excepto para void, los tipos de datos básicos tienen varios modificadores que los
proceden. Se usa un modificador para alterar el significado de un tipo base para
encajar con las necesidades diversas mas precisamente. En otras palabras
estos modificadores de tipos combinados con los tipos de datos fundamentales
dan paso a diferentes tipos de almacenamiento.
Modificador de
Tipo
Descripción
Signed Forza al compilador a utilizar un tipo de dato con signo si
antes se declaró como de tipo unsigned.Unsigned Se aplica a los tipos de datos enlistados arriba, su efecto
es eliminar el signo a el tipo de dato aplicado, por
ejemplo, para un tipo de dato int podemos especificarunsigned int en cuyo caso el rango para el tipo de dato
int cambia de ser -2147483648 a 2147483647, por éste
nuevo rango: 0 a 4294967295.long Un número entero de 32 bits de rango igual a
-2147483648 a 2147483647.Short Un número de 16 bits de rango igual a -32763 a 32762.Volatile Específica una variable que almacena datos cuyo
contenido puede cambiar en cualquier momento sea por
la acción del programa ó como reacción de la interacción
del usuario con el programa.Auto Es lo mismo que si no se usara ningún modificadorRegister El compilador procurará almacenar la variable cualificada
de este modo en un registro de la CPU.Extern La variable se considera declarada en otro fichero. No se
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 29
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 30/212
le asignará dirección ni espacio de memoria.Static Cuando se invoca a una función por segunda vez se
pierden los valores que las variables locales de la función
tenían al acabar la anterior llamada. Declarando una
variable de este tipo cuando se llama por segunda vez a
la subrutina la variable static (estática) contiene el mismo
valor que al acabar la llamada anterior.
Conversiones de tipo
Cuando se mezclan constantes y variables de diferentes tipos en una expresión,
C++ las convierte en el mismo tipo. El compilador de C++ convertirá todos los
operandos al tipo del operando mas grande en una operación según la base de
esta operación.
Reglas de conversión de tipos
1. Todos los char y short int se convierten a int.
Todos los float a double
2. Para todo par de operandos, lo siguiente ocurre en secuencia:
Si uno de los operandos es long double, el otro se convierte a long double.Si uno de los operandos es double el otro se convierte a double
Si uno de los operandos es long, el otro se convierte a long.
Si uno de los operandos es unsigned, el otro se convierte a unsigned.
Después de que el compilador aplique estas reglas de conversión, cada par de
operandos será del mismo tipo, y el resultado de la operación será del tipo de los
operandos.
Ejemplo:
char c;
int i;
float f;
c = 65;
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 30
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 31/212
i = 10;
f = i + c;
La variable c se convierte a “int” al hacer la suma i + c, al realizar la asignación
el resultado de la suma se convierte a “flota”.
Construcción cast
Se usa para forzar la conversión explícita de tipos de datos.
Listado
// lconst.cpp
// Ejemplo de constantes literales
#include <iostream>
using namespace std;
int main(){
cout << endl << 1/2;
cout << endl << 1.0/2;
cout << endl << float(1)/2;
return 0;
}
Salida
0
0.5
0.5
Nota:
En la última línea se usa la construcción cast para forzar la conversión explícita
del tipo de dato.
Ejercicio
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 31
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 32/212
Quite la construcción cast (Sustituya la línea: cout << endl << float(1)/2; por
cout << endl << 1/2;) ejecute el programa y discuta con sus compañeros la
salida del programa modificado.
1.6.2 Tipos de datos definidos por el usuario
Los tipos definidos por el usuario es la creación de un tipo de dato mediante la
combinación de los tipos de datos existentes y se definen como uniones,
enumeraciones, tipos definidos (typedef), estructuras o clases. Las estructuras y
uniones son tipos de clase (El tipo clase –class- se estudia brevemente en el
capitulo 3 y extensamente en el capitulo 4).
Uniones
Una unión es una localidad de memoria la cual es usada por dos o más
variables diferentes; generalmente de tipos diferentes. Cuando una unión es
declarada, el compilador crea una variable de la longitud de la variable mayor
definida en la unión. Solo un dato puede estar activo en un momento
determinado de la lista de datos que formen la unión.
Forma general:union etiqueta {
tipo nombre_de_variable;
.
.
.
tipo nombre_de_variable;
} variable_union;
Ejemplo:
union int_char {
int i;
char c;
};
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 32
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 33/212
union int_char dosv;
En la unión dosv, las 2 variables el “int” y el “char” comparten la misma localidad
de memoria, el dato “int” ocupa toda la memoria disponible y el dato “char” solo
una parte.
Para acceder a una variable de la “union” se utiliza el operador de acceso “.” o “-
>” según sea el caso (“->” para punteros, estos serán estudiados en el capitulo
3):
Ejemplo:
dosv.c = ‘x’;
fig 4. Ejemplo de la comparticion de memoria usada por la unión en una
maquina de 16 bits.
Uniones anónimas
Las uniones anónimas son aquellas que no tienen etiqueta y no se utilizan para
nombrar un objeto.
Forma general:
union {
tipo nombre_de_variable;
.
.
.
tipo nombre_de_variable;
};
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 33
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 34/212
Sus miembros pueden ser accedidos directamente en el ámbito de su
declaración sin necesidad de usar ninguno de los operadores de acceso
x.y o p->y.
Listado
// union.cpp
// Ejemplo de union con etiqueta y union anonima
#include <iostream>
using namespace std;
int main(){
union { float f; char c; };
union int_char { int i; char c; };
int_char dos_var;
c = 'X';
dos_var.c = 'Y';
cout << dos_var.c << "\t" << c << endl;
return 0;
}
Salida
Y X
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 34
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 35/212
Enumeraciones
Una enumeración es un conjunto de nombres de constantes enteras las cuales
especifican todos los valores legales que debe tener un tipo de variable.
Forma General:
enum nombre {lista de enumeración} lista_variables;
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 35
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 36/212
Typedef
Declara identificadores que se pueden utilizar para dar nombres a tipos de datos
básicos o derivados excepto funciones. El identificador se transforma en el
equivalente sintáctico a una palabra reservada.
Forma general:
typdef nombre_tipo;
Ejemplo:
Definición de la palabra “Entero”:
typedef int Entero;
Uso:
Entero n;
Estructuras
Una estructura es un método lógico de organizar datos y funciones (ver capitulo
de funciones”). La estructura es un patrón a seguir para crear variables de tipo
estructura. Al definir una estructura se crea un tipo de dato definido por el
usuario, y este tipo sirve para crear instancias de este tipo de dato.
Se puede ver como un conjunto de una o más variables, posiblemente de tipos
diferentes, agrupadas bajo un mismo nombre. Principalmente se usa para
organizar datos y esta parte es la que se describe a continuación.
Forma general:
struct etiqueta {
tipo nombre_variable;
tipo nombre_variable;
.
.
tipo nombre_variable;
} variables_de_estructura;
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 36
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 37/212
Para acceder a los elementos de la estructura:
nombre_estructura.nombre_elemento
Listado// structFecha.cpp
// Estructuras
#include <iostream>
using namespace std;
// definicion de la estructura (tipo)
struct Fecha {
int dd;
int mm;
int aa;
};
int main() {
Fecha fecha; // Declaracion de una variable de tipo estructura
cout << "Numero de dia ";
cin >> fecha.dd;
cout << "Numero de mes ";
cin >> fecha.mm;
cout << "A#o ";
cin >> fecha.aa;
cout << fecha.dd << "/" << fecha.mm << "/" << fecha.aa;
return 0;
}
Salida
Numero de dia 24
Numero de mes 12
A#o 2010
24/12/2010
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 37
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 38/212
struct Fecha {
int dd;
int mm;
int aa;
};
Estas líneas definen la estructura, aquí solo se crea el tipo de dato definido por
el usuario llamado Fecha.
Fecha fecha;
Se declara la variable fecha del tipo Fecha, que es del tipo de estructura definida
anteriormente.
cin >> fecha.dd;
Se ingresa desde la entrada estándar, un valor y se le asigna al elemento entero
“dd” que es parte de la variable fecha.
1.7 Palabras reservadas
Las palabras reservadas son identificadores utilizados por el lenguaje para fines
especiales, y no pueden ser utilizadas para por ejemplo nombrar variables,
clases, funciones, etc.
La siguiente tabla contiene las palabras reservadas del lenguaje divididas en las
palabras que provienen del lenguaje C, las que cambiaron su significado al
trasladarse al C++, y las exclusivas de C++.
Lenguaje C De C sobrecargadas en C++ Lenguaje C++Auto Struct andBreak Static and_eqcase Const asmchar enum bitandconst bitor
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 38
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 39/212
continue booldefault catchDo classdouble complelse const_castenum deleteextern dynamic_castfloat explicitfor exportgoto falseIf friendint inlinelong mutableregister namespace
return newshort notsigned not_eqsizeof operatorstatic orstruct or_eqswitch privatetypedef protectedunion publicunsigned reinterpret_cast
void static_castvolatile template
while thisthrowtruetrytypeidtypenameusinvirtual
w_charxorxor_eq
1.8 Expresiones
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 39
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 40/212
“Una expresión es una secuencia de operadores y operandos que especifica un
calculo. Una expresión puede dar como resultado un valor y puede originar
efectos secundarios (efectos colaterales)” (Ellis/Stroustrup 1994)
Sintaxis de las expresiones C++
Las expresiones son definidas recursivamente, de forma que las subexpresiones
pueden ser anidadas sin ningún límite formal, aunque quizás el compilador
pueda reportar un error de límite de memoria si no puede compilar una
expresión muy compleja.
1.9 Estructuras de ControlLas estructuras de control determinan el flujo de ejecución de las instrucciones,
mediante estas estructuras se puede controlar en orden y las veces que se
ejecutan las instrucciones.
1.9.1 Asignación
El hecho que las expresiones sean definidas recursivamente permite porejemplo la asignación múltiple.
Ejemplo:
int x, y, z;
x = y = z = 0;
Todas las variables se inicializan a cero.
1.9.2 Selección
C++ cuenta con dos tipos de tratamiento de condiciones, para condiciones de
cierto / verdadero y para condiciones múltiples.
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 40
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 41/212
if-else
Permite seleccionar la ejecución de dos bloques de código mediante la
evaluación de una condición.
Forma general 1:
if (expresión)
bloque de código;
Si la expresión es verdadera se ejecuta el bloque de código, si la
expresión es falsa no se ejecuta el bloque de código.
Forma general 2:
if (expresión)bloque de código 1;
else
bloque de código 2;
Si la expresión es verdadera se ejecuta el bloque de código 1, si la
expresión es falsa se ejecuta el bloque de código 2.
Donde expresión:
a) variables de tipo boolean
b) operación con operadores aritméticos, lógicos y/o relaciónales
Donde bloque de código:
a) una sola instrucción
b) {
varias instrucciones
}
Listado
// adivina.cpp
// Ejemplo if..else
// juego de adivina el numero que la computadora genera aleatoriamente
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 41
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 42/212
#include <iostream>
#include <ctime>
using namespace std;
int main() {
int n, pc;
srand( (unsigned)time( NULL ) );
pc = rand() % 5;
cout << "\nAdivina el numero que pienso (0-4) " << endl;
cin >> n;
if (n == pc)
cout << "Adivinaste!";
else
cout << endl << "Intenta otra vez";
return 0;
}
Salida en base a la entrada de ejemplo
Adivina el numero que pienso (0-4)
2
Intenta otra vez
#include <ctime>;“ctime” es para usar la función “time()” para plantar la semilla de la función
“rand()”.
srand( (unsigned)time( NULL ) );
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 42
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 43/212
La función “srand”, se usa para plantar la semilla de los números aleatorios
usando el tiempo regresado por la función “time()”, el “NULL” dentro de “time()”
es para que agarre el tiempo actual.
pc = rand() % 5;
“rand()”, genera el número aleatorio, el “% 5”, le dice que genere un numero en
un rango de 5 números, desde el 0 hasta el 4.
En el resto del código se lee un número de la entrada y lo compara con el
número generado en forma aleatoria, “if (n == pc)”, en caso que la evaluación
sea verdadera despliega “Adivinaste!” de lo contrario despliega “Intenta otra
vez”.
Los bloques a seleccionar mediante la condición están compuestos solo por una
línea y mediante el punto y coma el compilador sabe exactamente cual bloque
pertenece a la parte del “if” y cual a la del “else“.
Note que al final de la comprobación de la condición del “if” este no tiene un
punto y coma sino hasta el final de la sentencia:
if (n == pc)
cout << "Adivinaste!";
Igual pasa con la sentencia “else”, el punto y coma esta al finalizar la línea que
va a ejecutarse en caso de que la condición hecha en el encabezado del if no
se cumpla:
else
cout << endl << "Intenta otra vez";
En caso de que el bloque a ejecutar al hacerse la selección se componga de
mas de una línea de código hay que indicarle al compilador donde empieza este
bloque mediante el uso de la llave que abre “{“ y también donde termina el
bloque de instrucciones utilizando la llave que cierra “}”.
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 43
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 44/212
Ejemplo:
if (n == pc)
{
cout << "Adivinaste!" << endl;
cout << "\t\tTienes poderes siquicos?" << endl;
}
else
{
cout << endl << "No le atinaste";
cout << endl << "\t\tIntenta otra vez";
}
Otras combinaciones pueden ser por ejemplo:
if (n == pc)
{
cout << "Adivinaste!" << endl;
cout << "\t\tAcaso tienes poderes siquicos?" << endl;
}
else
cout << endl << "Intenta otra vez";
También:
if (n == pc)
cout << "Adivinaste!" << endl;
else
{
cout << endl << "No le atinaste";
cout << endl << "\t\tIntenta otra vez";
}
Las llaves de inicio y fin de bloque se pueden usar aunque sea solo una
sentencia, por ejemplo lo siguiente es perfectamente valido:
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 44
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 45/212
if (n == pc)
{
cout << "Adivinaste!" << endl;
}
else
{
cout << endl << "Intenta otra vez";
}
En el siguiente fragmento de código el “else” no tiene llaves, por lo tanto el
bloque de instrucciones perteneciente al “else” es de una sola línea:
if (n == pc){
cout << "Adivinaste!" << endl;
cout << "\t\tAcaso tienes poderes siquicos?" << endl;
}
else
cout << endl << "No le atinaste";
cout << endl << "\t\tIntenta otra vez";
La ultima línea en este fragmento de código no pertenece al “else”, esta línea
siempre se ejecuta no importa si se cumple la condición del “if” o no; lo único
que tiene es la sangría y a simple vista pudiera parecer que pertenece al cuerpo
del “else”.
En el siguiente ejemplo el bloque de código perteneciente al “if” es de una sola
línea ya que no tiene llaves:
if (n == pc)
cout << "Adivinaste!" << endl;
cout << "\t\tAcaso tienes poderes siquicos?" << endl;
else
{
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 45
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 46/212
cout << endl << "No le atinaste";
cout << endl << "\t\tIntenta otra vez";
}
El “if” se compone realmente por:
if (n == pc)
cout << "Adivinaste!" << endl;
La línea que le sigue está fuera del “if”:
cout << "\t\tAcaso tienes poderes siquicos?" << endl;
El “else” no forma parte del “if” porque este termino con el punto y coma, por lotanto marca un error de sintaxis por el compilador ya que “else” solo puede ir
acompañado de un “if”.
else
{
cout << endl << "No le atinaste";
cout << endl << "\t\tIntenta otra vez";
}
Al mostrar el párrafo de código anterior con sangría se aprecia mas el error (otra
razon del porque utilizar sangrías)
if (n == pc)
cout << "Adivinaste!" << endl;
cout << "\t\tAcaso tienes poderes siquicos?" << endl;
else
{
cout << endl << "No le atinaste";
cout << endl << "\t\tIntenta otra vez";
}
Ejercicios
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 46
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 47/212
1. Modifique el programa “condolar.cpp”, para presentarle al usuario la opción
de convertir de dolares a pesos y de pesos a dólares, realice la operación
seleccionada por el usuario.
2. Realice un programa que lea un número de la entrada estándar y despliegue
si el número leído es par o impar, utilice el operador “%” para obtener el
residuo de la división, note que el residuo de una división entre dos de un
número par siempre es cero.
Evaluación de la expresión
En C++ la evaluación de la expresión dentro de los paréntesis después del “if”,
para que sea verdadera debe ser distinta de cero y es falsa cuando es cero.Ejemplo:
if (1)
cout << “Expresion verdadera”; // <-- se imprime esto en pantalla
if (0)
cout << “Expresion verdadera”;
else
cout << “Expresion falsa”; // <-- se imprime esto en pantalla
El lenguaje C++ no pone restricción al tipo de expresiones a solo las que
invocan operadores relacionales y lógicos. Todo lo que se requiere es que la
expresión evaluada de cero o no cero.
Listado
// divide.cpp
// Divide el primer numero por el segundo
#include <iostream>
using namespace std;
int main() {
float a, b;
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 47
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 48/212
cout << endl << "Introduce dos numeros enteros: ";
cin >> a >> b;
if (b) // equivalente a (b != 0)
cout << a/b << endl;
else
cout << "No puedo dividir por cero" << endl;
return 0;
}
Salida en base a la entrada de ejemplo
Introduce dos numeros enteros: 3
0
No puedo dividir por cero
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 48
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 49/212
if (b)
Evalúa si la variable es distinta de cero (verdadero) o cero (falso)
if anidado
Se le llama “if” anidado cuando un bloque de código perteneciente a un “if-else”
contiene otro “if” o “if-else”.
Listado
// mayor.cpp
// compara dos numeros y dice si son iguales o cual es el mayor
#include <iostream>
using namespace std;
int main(){
int a, b;
cout << "\nDame un numero ";
cin >> a;
cout << "Dame otro numero ";
cin >> b;
if (a == b)
cout << "Los numero son iguales";
else
if (a > b)
cout << "El numero " << a << " es mayor que " << b;
else
cout << "El numero " << b << " es mayor que " << a;
return 0;
}
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 49
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 50/212
Salida en base a la entrada de ejemplo
Dame un numero 12
Dame otro numero 3
El numero 12 es mayor que 3
if (a == b)
cout << "Los numero son iguales";
else
if (a > b)
cout << "El numero " << a << " es mayor que " << b;
else
cout << "El numero " << b << " es mayor que " << a;
El segundo “if” se encuentra dentro del bloque de código perteneciente al “else”,
ambos “if” tienen la parte del “else”, cuando esto no sucede se puede prestar a
confusiones.
Ejemplo:
if (a != b)
if (a > b)cout << "El numero " << a << " es mayor que " << b;
else
cout << "El numero " << b << " es mayor que " << a;
En esta situación el último “else” pertenece al “if” inmediato anterior.
if (a != b)
if (a > b)
cout << "El numero " << a << " es mayor que " << b;
else
cout << "numeros iguales ";
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 50
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 51/212
Aquí aunque el “else” este alineado con el primer “if”, este sigue perteneciendo
al “if” inmediato anterior, para lograr que el “else” pertenezca al primer “if” se
necesita utilizar las llaves de inicio y fin de código.
if (a != b)
{
if (a > b)
cout << "El numero " << a << " es mayor que " << b;
}
else
cout << "numeros iguales ";
switch
La sentencia “switch” es usada para decisiones múltiples que comprueba si una
expresión iguala uno entre varios valores constantes.
Forma General:
switch (variable) {
case constante1:
bloque de código;
case constante2:
bloque de código;
break;
.
.
.
default:
bloque de código;
}
Descripción
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 51
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 52/212
1. El “switch” difiere del “if” porque la primera solo puede comprobar por
igualdad, mientras que la expresión condicional del “if” puede ser de cualquier
tipo.
2. No pueden tener dos constantes case con idénticos valores en el mismo
“switch”. Una sentencia “switch” que esta encerrada por otro “switch” puede
tener constantes case que son las mismas.
case
Actúa como una etiqueta.
break
Opcional dentro de la sentencia “switch”. Se usa para terminar la secuencia queesta asociada con cada constante. Si se omite, la ejecución continuara en las
sentencias del siguiente case hasta encontrar un “break”, un “return” o el final
del “switch”.
default
Es opcional y se ejecuta si no se satisface ninguna opción.
Listado
// fechaSwitch.cpp
// demostracion del switch
#include <iostream>
using namespace std;
int main(){
int iMes = 9;
cout << iMes << " ";
switch(iMes) {
case 1:
cout << "enero";
break;
case 2:
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 52
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 53/212
cout << "febrero";
break;
case 3:
cout << "marzo";
break;
case 4:
cout << "abril";
break;
case 5:
cout << "mayo";
break;
case 6:
cout << "junio";
break;
case 7:
cout << "julio";
break;
case 8:
cout << "agosto";
break;
case 9:
cout << "septiembre";
break;
case 10:
cout << "octubre";
break;
case 11:
cout << "noviembre";
break;
case 12:
cout << "diciembre";
break;default:
cout << " *error*";
}
return 0;
}
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 53
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 54/212
Salida
9 septiembre
int iMes = 9;
La variable mes es inicializada al momento de declararla, al entrar al “switch”
este compara la variable “iMes” con las constantes literales en los cases hasta
encontrar el “case 9:” y se ejecuta la línea debajo de este desplegando
“septiembre”, a continuación se ejecuta la siguiente línea conteniendo la
instrucción “break” la cual rompe el “switch”.
En caso que la variable no se encuentre en ninguno de los case, se ejecuta lasentenciaque le sigue a “default”.
Note el uso del “break” al terminar cada case, esto es necesario para que
termine la ejecución del “switch” y no continué con los siguientes case, lo cual es
útil en algunas situaciones, como en el siguiente programa por ejemplo.
Listado
// switch_dolar.cpp
// Convierte dolares a pesos o viceversa, pide el tipo de cambio
// ejemplo del switch con las clasusulas case sin el break
#include <iostream>
using namespace std;
int main(){
char opcion;
float dolares, pesos, cambio;
cout << "Cual es el tipo de cambio? ";
cin >> cambio;
cout << "*** M E N U ***" << endl
<< "ingrese la primera letra de la palabra"
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 54
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 55/212
<< endl;
cout << "D olares a pesos" << endl;
cout << "P esos a dolares" << endl;
cout << "Opcion? ";
cin >> opcion;
switch (opcion) {
case 'd':
case 'D':
cout << endl << "Cuantos dolares desea convertir a pesos? ";
cin >> dolares;
pesos = dolares * cambio;
cout << "Pesos = " << pesos;
break;
case 'p':
case 'P':
cout << endl << "Cuantos pesos desea convertir a dolares? ";
cin >> pesos;
dolares = pesos / cambio;
cout << "Pesos = " << dolares;
break;
default:
cout << "opcion no implemenrada";
}
return 0;
}
Salida en base a la entrada de ejemplo
Cual es el tipo de cambio? 12.5
*** M E N U ***
ingrese la primera letra de la palabra
D olares a pesos
P esos a dolares
Opcion? d
Cuantos dolares desea convertir a pesos? 18
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 55
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 56/212
Pesos = 225
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 56
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 57/212
case 'd':
case 'D':
cout << endl << "Cuantos dolares desea convertir a pesos? ";
cin >> dolares;
pesos = dolares * cambio;
cout << "Pesos = " << pesos;
break;
El “case ‘d’:” no contiene un “break” (ni código) por lo tanto si el usuario del
programa ingresa una ‘d’ minúscula entra a este “case” continua hacia abajo y
se ejecuta el código del “case” con la ‘D’ mayúscula, el cuerpo de este “case”
tiene un “break” porque no debe ejecutar lo que esta en el siguiente “case”.
Ejercicios
1. Modifique el programa “fechaSwitch.cpp” para que pida el mes del teclado
2. Escriba un programa que lea un carácter del teclado y si se trata de un
número despliegue el número con letra, si no es un número mencionarlo,
utilize la sentencia “switch”.
3. Discuta la posibilidad de hacer un programa que escriba su nombre completo
100 veces; 10,000 veces?; 9,000,000 de veces?
1.9.3 Iteración
Las sentencias de repetición permiten ejecutar una porción de código varias
veces.
do-while
Hace la comprobación al final después de cada pasada a través del cuerpo delciclo. Y este se ejecuta al menos una vez.
Forma general:
do
bloque de código;
while (expresión);
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 57
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 58/212
Listado
// doadivina.cpp
// do..while, adivina el numero generado aleatoriamente
// Termina cuando el usuario así lo desea
#include <iostream>
#include <ctime>
using namespace std;
int main() {
int n, pc;
char c;
srand( (unsigned)time( NULL ) );
pc = rand() % 5;
do {
cout << "\nAdivina el numero que pienso (0-4) " << endl;
cin >> n;
if (n == pc)
cout << "ADIVINASTE!!!" << endl;
else
cout << "NO ES!!!" << endl;
cout << endl << "Intenta otra vez? (s/n)";
cin >> c;
} while (c != 'n');
return 0;
}
Salida en base a la entrada de ejemplo
Adivina el numero que pienso (0-4)
1
NO ES!!!
Intenta otra vez? (s/n)s
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 58
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 59/212
Adivina el numero que pienso (0-4)
3
ADIVINASTE!!!
Intenta otra vez? (s/n)n
Este es el ejemplo adivina.cpp presentado en el listado 2.1, pero dentro de un
ciclo.
do {
Inicia el ciclo, línea 14, en la línea 22 y 23 pregunta si se quiere continuar
intentando.
} while (c != 'n');
En la línea 24, checa lo que se leyó en la variable c y la compara, con en caso
que sea verdadera la evaluación el ciclo termina, de lo contrario regresa al do {.
Ejercicios
1. Modifique el programa “switch_dolar.cpp”, que lee un carácter del teclado y sise trata de un número despliega el número con letra y si no es un número lo
menciona para que termine hasta que se ingrese una 'X'.
2. Discuta como se puede mejorar el ejemplo anterior (“doadivina.cpp”), por
ejemplo, ¿que sucede si el usuario adivina el número y desea seguir
jugando?, realice las modificaciones sugeridas.
3. Hacer un programa que escriba su nombre completo 10,000 veces
while
Hace la comprobación al inicio de cada pasada a través del cuerpo del ciclo. Si
la evaluación es falsa no se ejecuta ni una sola vez.
Forma general:
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 59
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 60/212
while (expresión)
bloque de código;
Listado
// ascii.cpp
// Despliega la tabla Ascii en la salida estándar
#include <iostream>
using namespace std;
int main() {
int i;
i = 0;
while (i < 256) {
// el caracter 26, puede borrar pantalla
cout << char(i) << " " << i << " ";
i++;
}
return 0;
}
Salida
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 60
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 61/212
while (i < 255) {
Se evalúa la variable “i” si es menor a 255 empieza el ciclo y se ejecuta la
primera sentencia después de la llave “{“ así sucesivamente hasta que se
encuentra la llave que cierra “}” al pasar esto, se evalúa la condición dentro de
los paréntesis del “while” si la “i” todavía es menor a 255 vuelve a ejecutar unapor una las instrucciones dentro de las llaves “{“ y “}”, cuando la variable “i” sea
igual a 255 el ciclo termina.
La instrucción char(i), regresa el carácter ASCII correspondiente al entero de la
variable “i”.
for
Forma general:
for (inicialización; condición; incremento)
bloque de código;
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 61
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 62/212
Gramaticalmente, los tres componentes de un “for” son expresiones. Mas
comúnmente, inicialización e incremento son asignaciones o llamadas a función
y condición es una expresión de relación.
Puede omitirse cualquiera de las tres partes, aunque deben permanecer los
puntos y comas.
Ejemplo:
for (; ;)
;
Este es un ciclo infinito; que podríamos terminar con un “break” o con un
“return”.
La proposición for es equivalente a:inicialización;
while (condición) {
bloque de código;
incremento;
}
Listado
// for_prom.cpp
// ejemplo del for el promedio de la suma de 5 números
#include <iostream>
using namespace std;
int main() {
float fCalificacion, fSuma, fPromedio;
int i;
cout << "Ingresa calificaciones " << endl;
fSuma = 0;
for (i = 0; i < 5; i++) {
cout << i << ". Calificacion? ";
cin >> fCalificacion;
fSuma = fSuma + fCalificacion;
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 62
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 63/212
}
fPromedio = fSuma / 5;
cout << endl << "El promedio es " << fPromedio;
return 0;
}
Salida en base a la entrada de ejemplo
Ingresa calificaciones
0. Calificacion? 100
1. Calificacion? 95
2. Calificacion? 90
El promedio es 95
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 63
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 64/212
for (i = 0; i < 5; i++) {
Inicia el ciclo “for” ejecutándose primero la parte de inicialización “i = 0;”
después se evalúa “i < 5;” la primer a vez se cumple la condición y entra al
cuerpo del “for”, en el cuerpo del “for” (todas las sentencias que están en medio
de la llave que abre “{“ que le sigue al “for” y la llave que cierra “}”
correspondiente) se pide la calificación y se acumula en “fSuma”.
Al terminar el cuerpo del “for” regresa a la línea 12 e incrementa i++ después
evalúa i < 5, si la evaluación es verdadera vuelve al cuerpo del for si no es así
termina (nótese que después de la primera vez que se ejecuta el for , ya no se
realiza la parte de inicialización y el encabezado del for se evalúa de derecha a
izquierda)
fPromedio = fSuma / TAM;
En la línea 17 se calcula el promedio y lo despliega en la siguiente línea.
Ejercicios
1. Modifique programa ejemplo “for_prom.cpp” para que utilice la iteración
“while” en vez del “for”.
2. Modifique el programa ejemplo “ascii.cpp” para que utilice la iteración “for” en
vez del “while” (asciifor.cpp) .
3. Discuta la posibilidad de hacer un programa
a) Que almacene 3 números y los despliegue en orden de menor a mayor
b) Que almacene 100 números y los despliegue en orden de menor a mayor
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 64
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 65/212
Capitulo 2
Subprogramas
2.1 Definición de un subprograma
En C++ un programa puede crearse como un grupo de bloques,
donde cada bloque contiene código lo más independiente
posible y comprobable llamado subprograma. Los subprogramas
contienen entradas y salidas para conectarlos a otros
bloques de código –subprogramas- para formar el programaprincipal.
La división de un programa en subprogramas es parte de una
técnica de programación llamada programación modular; la
cual es basada en la filosofía de “divide y vencerás”.
Módulos
Un modulo es un conjunto encapsulado de datos y operaciones que tienen relación entre si. Enel caso de C++ lo común es que sea en un archivo de encabezado y en un archivo de
implementación.
La utilización de módulos es para formar partes de código independiente con el propósito de
reducir la complejidad, aumentar y facilitar la reutilización del código además de hacer más
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 58
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 66/212
mantenible los programas. “La modularidad es la capacidad de dividir el problema en pequeñas
partes independientes entre si” [Hernandez 2002]
fig1. Organización de programas mediante módulos
2.1.1 Estructura de un subprograma
Un subprograma se implementa en C++ mediante funciones. Una
función es una o más instrucciones en designadas para una
tarea especifica, a este conjunto de instrucciones se le
asigna un nombre, que identifica la función dentro del
programa.
Los programas en C++ cuentan con una función especial llamada main() esta es llamada
automáticamente al iniciar la ejecución del programa; dentro de esta función se realizanllamadas a objetos y/o otras funciones.
El código de una función es privado a la función y no puede ser accesado por ninguna
declaración en ninguna otra función excepto a través de argumentos y variables globales.
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 59
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 67/212
Las variables definidas dentro de una función son variables locales dinámicas (empiezan a existir
cuando la función es llamada y se destruyen al terminar).
Forma general:
especificador_tipo nombre_funcion(lista_de_argumentos)
{
cuerpo de la función
<return valor>
}
La lista_de_argumentos es una lista de nombres de variables separados por comas que recibe
los valores de los argumentos cuando se llama la función.
El especificador_de_tipo es el tipo de valor que la función devuelve mediante el “return”.
2.1.2 Valor de retornoLas funciones terminan cuando se encuentra la última llave o mediante la sentencia “return” y
devuelven el control de flujo del programa automáticamente al procedimiento que la llamó.
Listado
// linea.cpp
// Funcion que dibuja una linea de 40 guiones
#include<iostream>using namespace std;
void linea() {
int i;
for (i = 0; i < 40; i++)
cout << "-";
}
int main() {
linea();
cout << endl << "Este mensaje es importante" << endl;
linea();
return 0;
}
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 60
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 68/212
Salida
----------------------------------------
Este mensaje es importante
----------------------------------------
void linea()
“linea” es el nombre de la función, y “void” antes del nombre indica que esta función no va a
regresar un valor al proceso que la llame, el paréntesis que abre y el paréntesis que cierra
después del nombre indican que es una función, entre estos paréntesis se ponen los argumentos
de la función, en este caso la función no necesita argumentos.
linea()
En la primera línea de la función “main” se hace el llamado a la función definida anteriormente,note que aunque la función no recibe parámetros el uso de los paréntesis es obligatorio.
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 61
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 69/212
Nota:
La función “linea()” esta definida antes de la función “main()” esto es para que el compilador ya la
conozca cuando se haga la llamada dentro de “main()”, si se escribiera la función “linea()” abajo
o en otro archivo, abría que poner la declaración arriba del “main()”, ya sea escribiéndola
directamente en el archivo principal o en un archivo de encabezado, mediante un “#include”.
2.2 Declaración de un subprograma
La declaración de un subprograma llamada en C++ prototipo de
función se refiere a solo escribir el encabezado de la
misma. Cuando la implementación se codifica después de que
la función es llamada o en un archivo aparte de donde se
manda llamar se debe incluir el encabezado de la función
antes de que esta sea llamada, esto es para que el
compilador verifique si la sintaxis con que se llamó la
función definida por el usuario es correcta. “Decirle al
compilador que la función existe y como es llamada” [Eckel
1993]
Listado
// proto_linea.cpp
// Ejemplo de prototipo de funciones
// Funcion que dibuja una linea de 40 guiones
#include<iostream>
using namespace std;
void linea();
int main() {
linea();
cout << endl << "Este mensaje es importante" << endl;
linea();
return 0;
}
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 62
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 70/212
void linea() {
int i;
for (i = 0; i < 40; i++)
cout << "-";
}
Salida
----------------------------------------
Este mensaje es importante
----------------------------------------
2.3 Bibliotecas o librería de subprogramasLas librerías son una manera de añadir funcionalidad al lenguaje sin agregar palabras
reservadas al lenguaje, por ejemplo una función puede ser compilada y almacenada en una
librería o archivo, de donde el encadenador la extrae.
El proveedor del compilador generalmente proporciona bibliotecas estándar de funciones y
clases. Los proveedores de software independientes proporcionan bibliotecas de propósito
especial.
Tipos de librerías
En C++ existen dos tipos fundamentales de librerías: estáticas y dinámicas. En ambos casos
junto a las librerías (archivos con la extensión .lib, .a, .dll etc) se incluyen archivos "de cabecera",
archivos con la extensión .h estos archivos contienen las declaraciones de las entidades
contenidas en la librería, así como las macros y constantes predefinidas utilizadas en ella. Es
decir, la "interfaz" de las funciones o clases que utilizará. En el caso de funciones esto se
concreta en el prototipo; en el caso de clases, en la especificación de sus métodos y
propiedades públicas*. (http://www.zator.com/Cpp/E1_4_4b.htm)
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 63
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 71/212
Estáticas
Son también denominadas librerías-objeto, son colecciones de archivos objeto (compilados)
agrupados en un solo archivo con la extensión .lib, .a, etc. junto con uno o varios archivos de
cabecera (generalmente con la extensión “.h”).
Los componentes utilizados de estas librerías quedan incluidos en el programa ejecutable.
Dinámicas
Son las denominadas librerías de enlazado dinámico, es decir los componentes utilizados se
agregan cunado el programa se esta ejecutando y permite que la misma librería pueda ser
usada por varios ejecutables sin necesidad que se embeba permanentemente en un solo archivo
ejecutable. Generalmente conocidas como DLLs, acrónimo de su nombre en inglés ("Dynamic
Linked Library"). Estas librerías se utilizan mucho en la programación para el Sistema Operativo
Windows.
Listado
// tolower.cpp
// Muestra el uso de la funcion tolower
// que convierte un caracter a minusculas
#include <iostream>
using namespace std;
int main() {
char a, b, c;
a = 'R';
b = tolower(a);
cout << a << " " << b;
cout << endl << "Ingrese una letra en Mayusculas ";
cin >> c;
b = tolower(c);
cout << "Letra en minusculas " << b;
return 0;
}
Salida
R r
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 64
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 72/212
Ingrese una letra en Mayusculas Q
Letra en minusculas q
EjercicioModifique el programa doadivina.cpp –del cap 1- para que acepte minúsculas y mayúsculas
cuando pregunta si desea continuar, utilice la función “toupper()”.
Clase string
El tipo de dato string no existe en C++, este se implementa mediante tipo de dato definido por el
usuario mediante una clase (esta clase se incluye en una de las librerías del C++ estándar
proporcionadas por el compilador).
Un string es una clase para declarar objetos y estos objetos contienen básicamente una
secuencia de caracteres. Los programas que usen la clase string deben incluir la sentencia
“using namespace std” y el archivo de encabezado: #include <string>
Listado
// string1.cpp
#include <iostream>
#include <string>
using namespace std;
int main() {
string strNombre;
cout << "Cual es tu nombre? ";
cin >> strNombre;
cout << "\nSaludos " << strNombre << endl;
cout << "\nTu nombre tiene " << strNombre.length() << " letras";
return 0;
}
Salida
Cual es tu nombre? Batman
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 65
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 73/212
Saludos Batman
Tu nombre tiene 6 letras
strNombre.length()
Objeto “strNombre” llamando un metodo, la cual regresa cuantos caracteres tiene el string.
Nota:
Para ingresar oraciones (palabras con espacios intermedios) usar:
getline(cin, str, ‘\n’);
Donde str es un objeto de tipo string.
Ejercicio
Tome como base el ejemplo string1.cpp para hacer un programa donde declare
3 variables string s1, s2, s3
a) Asigne s1 y s2 con datos proporcionados por el usuario
b) Concatene s1 y s2 (s1 + s2 concatena los strings) dejando el resultado en s3
c) Despliegue el string s3
Nota:
Algunos compiladores de C++ incluyen subprogramas que no son parte de las librerías estándar,
esto facilita de alguna forma la programación, pero limita la portabilidad del código a otros
compiladores y/o plataformas.
2.4 Primer acercamiento a clases y objetosProgramación orientada a objetos
El objetivo principal de la programación orientada a objetos es facilitar las tareas de programar y
reutilizar el código, en una forma integrada y más modular que la estructurada.
Clase
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 66
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 74/212
Describe un conjunto de objetos los cuales tienen las mismas características (datos) y el mismo
comportamiento (código), una clase es realmente un tipo de dato definido por el usuario, es una
extensión del concepto del tipo de dato registro, el cual nos permite organizar diferentes tipos de
datos en un solo lugar. La clase nos permite combinar datos y código dentro de un solo paquete.
Objeto
Un objeto es una instancia de una clase, la clase es el tipo de dato y el objeto es la variable. Un
objeto tiene un estado, comportamiento e identidad. Una identidad porque cada objeto pose un
nombre (identificador) único, un estado porque los datos tienen un valor determinado
dependiendo del proceso en que se encuentre el objeto, y un comportamiento porque “sabe” que
hacer con esos datos, es decir tiene sus propios algoritmos para procesar sus datos.
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 67
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 75/212
Listado
// claseFecha.cpp
// Clases
#include <iostream>
#include <string>
using namespace std;
class Fecha {
public:
int dd;
string mm;
int aa;
};
main() {
Fecha fecha;
cout << "Dia ";
cin >> fecha.dd;
cout << "Mes en letra ";
cin >> fecha.mm;
cout << "A#o ";
cin >> fecha.aa;
cout << fecha.dd << " de " << fecha.mm << " de " << fecha.aa;
}
Salida en base a la entrada de ejemplo
Dia 12
Mes en letra enero
A#o 2009
12 de enero de 2009
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 68
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 76/212
2.5 Ámbito y tiempo de vida de variables
Alcance de variables
Los programas en C++ se forman a base de bloques de código estos bloques inician con la llave
“{“ y terminan con la llave “}”.
Las variables declaradas dentro de un bloque de código son locales a ese bloque, no pueden ser
accesadas por otro bloque o afuera de este.
Variables automáticas, también llamadas locales dinámicas
Cada variable local comienza a existir cuando se ejecuta el bloque donde fue declarada y
desaparece cuando el bloque de código acaba. Estas variables no conservan su valor entre dos
llamadas sucesivas.
Variables externas, también llamadas globales
Se definen fuera de las funciones, estas son externas a todas las funciones; esto es variables
globales a las que puede acceder cualquier función mediante su nombre. Cuando son
declaradas en otro archivo se debe usar la palabra reservada “extern”.
Listado
// alcance.cpp
// Ejemplo de alcance de variables y del operador de alcance ::
#include <iostream>
using namespace std;
int a = 0;
int main() {
int a = 10;
cout << a << endl;
cout << ::a << endl;
{
int x = 20;
cout << x << endl;
x++;
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 69
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 77/212
}
//cout << x;
return 0;
}
Salida
10
0
20
int a = 0;
Declara una variable global, para todos los bloques de código que le siguen hacia abajo, en estecaso el bloque de “main()” que empieza y el bloque sin nombre que empieza abajo del segundo
“cout”.
int a = 10;
Sobrescribe a la variable con el mismo nombre declarada anteriormente antes de empezar la
función “main()”.
El primer “cout” despliega el contenido de la variable local “a”.
El segundo “cout” despliega el contenido de la variable global, utilizando el operador de alcance
“::”
La llave que abre “{“ después del segundo “cout” indica el inicio de un bloque de código sin
nombre.
int x = 20;
Declara una variable local para el bloque que inicio en la
línea anterior, la variable empieza a existir aquí y termina
al cerrar el bloque con la llave que cierra “}”.
El ultimo “cout” esta como comentario porque marca un error, de variable no encontrada ya que
la variable “x” dejo de “existir” al terminarse el bloque sin nombre.
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 70
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 78/212
Espacio de nombres
Por omisión cuando un nuevo tipo de dato es definido este existe globalmente. Lo cual significa
que está disponible a cualquier función en la aplicación.
Para evitar conflictos entre las diferentes librerías (módulos de código para ser rehusado), cadalibrería puede crear su propio bloque de espacio de definición de datos, utilizando la palabra
reservada “namespace”.
namespace
Un espacio de nombres definido por la palabra “namespace” es el alcance en el cual los tipos de
datos pueden ser definidos para evitar la sobrecarga del espacio de alcance global.
El uso de “namespace” permite agrupar un conjunto de variables globales dentro de un nombre.
Es decir el alcance global se subdivide en espacios de nombres.
Forma general:
namespace identificador
{
cuerpo-del-namespace
}
using namespace
La directiva “using” seguida del “namespace” sirve para asociar el nivel en que un identificador
esta con cierto “namespace”, para que los objetos, funciones y variables de ese “namespace”
pueden ser accesibles directamente como si estuvieran definidos en el alcance global.
Forma general:
using namespace identificador;
Listado
// namespace.cpp
#include <iostream>
using namespace std;
namespace espacio1 {
int a = 0;
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 71
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 79/212
};
namespace espacio2 {
int a = 100;
};
int main() {
cout << "namespace espacio1 " << espacio1::a;
cout << "\nnamespace espacio2 " << espacio2::a;
return 0;
}
Salida
namespace espacio1 0
namespace espacio2 100
En este ejemplo se utiliza el operador de alcance :: para especificar que espacio de nombre
utilizar; para evitar poner el nombre cada vez que se use lo que esta definido en el espacio de
nombres se puede utilizar “using namespace”.
2.6 Argumentos y paso de parámetros.Hay tres tipos de argumentos para las funciones
Por valor
Por puntero*
Por referencia*
* Estos dos últimos se estudian en el siguiente capitulo de Punteros, referencias y arreglos.
Llamada por valor
Este método copia el valor del argumento dentro de los parámetros formales de la función y
todos los cambios que sufran los parámetros no afectan el valor del argumento usado para
llamar la función. Los parámetros formales de la función son las declaraciones de las variables
que aceptan los valores de los argumentos.
Listado
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 72
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 80/212
// sqr.cpp
// Usa una funcion que recibe y regresa un valor entero
#include <iostream>
using namespace std;
int sqr(int num) {
num = num * num;
return num;
}
int main() {
int n, x;
cout << "Ingresa un numero ";
cin >> n;
x = sqr(n);
cout << endl << "El cuadrado de " << n << " es " << x;
return 0;
}
Salida
Ingresa un numero 3
El cuadrado de 3 es 9
int sqr(int num) {
El primer “int” indica que la función regresa un valor de tipo entero y el segundo que recibe un
entero como argumento.
return num;
Aquí se regresa el valor contenido en la variable “num”, el tipo de dato que se regrese con
“return” debe de corresponder al tipo de dato que aparece antes del nombre de la función.
El “return” puede aparecer en cualquier parte del cuerpo de la función e inmediatamente regresa
el control a la línea de donde fue llamada la función, devolviendo el valor indicado después del
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 73
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 81/212
“return” en caso que exista tal valor ya que también puede estar solo y en ese caso solamente
regresará el control a la parte de donde fue llamada.
x = sqr(n);
La función es llamada con “n” como argumento y regresa el número indicado en el “return”
asignándoselo a la variable “ x ”.
Ejercicios
1 Escriba una función que reciba un número y regrese su valor absoluto.
2 Realice una función eleva(n, x) que eleve el valor de “n” a la potencia “x”, regrese el numero
elevado.
3 Hacer un programa que pruebe las funciones de un modulo compuesto de un archivo de
encabezado (.h) y un archivo fuente (.cpp) que contenga las siguientes funciones:
- Convierta de centímetros a pulgadas
- Convierta de pulgadas a centímetros
- Convierta de metros a yardas
- Convierta de yardas a metros
- Convierta de kilómetros a millas
- Convierta de millas a kilómetros
Argumentos por omisión
Si la función tiene un prototipo los argumentos por omisión
se declaran en el prototipo y no en la definición. Si la
función no tiene prototipos se pueden declarar en la
definición.
Hay que notar que no todos los argumentos deben de estar
definidos por omisión; puede ser uno solo pero este solo
puede estar al final de la lista de argumentos.
Ejemplo:
Formato(int x, int y, int z = 0);
Formato(int x, int y = 0, int z = 0);
Esto es valido, los últimos argumentos en la lista son
por defecto.
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 74
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 82/212
Formato(int x, int y = 0, int z);
Formato(int x = 0, int y, int z = 0);
Esto es inválido, una vez que se pone un argumento por
omisión en la lista todos los demás que le siguen deben
ser por omisión.
Listado
// omision.cpp
// Argumentos por omision de las funciones
// en los prototipos de las funciones de C++
#include <iostream>
using namespace std;
void muestra(int = 1, float = 2.3, long = 4);
int main() {
muestra(); // Los tres parametros por defecto
muestra(5); // Provee el primer parámetro
muestra(6, 7.8); // Provee los primeros dos
muestra(9, 10.11, 12L); // Provee los tres parametros
return 0;
}
void muestra(int pr, float seg, long ter) {
cout << "\n Primero = " << pr;
cout << ", Segundo = " << seg;
cout << ", Tercero = " << ter;
}
Salida
Primero = 1, Segundo = 2.3, Tercero = 4
Primero = 5, Segundo = 2.3, Tercero = 4
Primero = 6, Segundo = 7.8, Tercero = 4
Primero = 9, Segundo = 10.11, Tercero = 12
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 75
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 83/212
void muestra(int = 1, float = 2.3, long = 4);
Se declara el prototipo de la función con los argumentos por
omisión.
En el “main()” se manda llamar la función muestra() con
diferente número de argumentos para que se utilicen los
argumentos por omisión.
2.7 Sobrecarga de subprogramas.
La sobrecarga de subprogramas en C++ significa que se pueden tener varias funciones con elmismo nombre, esto es posible ya que el identificador de una función se determina por el
nombre de la función y sus argumentos. Las funciones deben diferir en la lista de argumentos, ya
sea en el número de variables que se pasan a la función, en el tipo de argumentos que recibe o
bien en el orden.
Listado
// sobrecarga.cpp
//Sobrecarga de una funcion
#include <iostream>
using namespace std;
int cuadrado(int); //prototipo de funcion sobrecargada
double cuadrado(double);//prototipo de funcion sobrecargada
int main() {
int ix = 5;
double dx = 1.5;
cout << "El cuadrado de "<< ix << " es "<< cuadrado(ix) << endl;
//el compilador al ver un valor int elige la funcion
cout << "El cuadrado de " << dx << " es " << cuadrado(dx) << endl;
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 76
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 84/212
return 0;
}
//Funcion sobrecargada para valores int
int cuadrado(int y ) {
return y*y;
}
//Funcion sobrecargada para valores double
double cuadrado(double y) {
return y*y;
}
Salida
El cuadrado de 5 es 25
El cuadrado de 1.5 es 2.25
2.8 RecursividadUna función es recursiva si una sentencia en el cuerpo de una función se llama a si misma.
Listado
// recursiva.cpp
// Usa una funcion normal y una recursiva para sacar el factorial
#include <iostream>
using namespace std;
int factorial(int n) { // no recursiva
int i, f = 1;
for (i = 1; i <= n; i++)
f = f * i;
return f;
}
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 77
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 85/212
int factorial_recusiva(int n) { // Funcion recursiva
if (n == 0)
return 1;
else
return n * factorial_recusiva(n-1);
}
int main() {
int n;
cout << "ingrese un numero ";
cin >> n;
cout << "El factorial de " << n
<< " es " << factorial(n) << endl;
cout << "El factorial de " << n
<< " es " << factorial_recusiva(n) << endl;
return 0;
}
Salida en base a la entrada de ejemplo
ingrese un numero 5
El factorial de 5 es 120El factorial de 5 es 120
Funciones inline
Las funciones en línea se declaran anteponiendo la palabra “inline” al tipo de dato de la función,
y éstas funciones actúan como macros; el compilador pone el código que se encuentra dentro de
la función en la parte donde está el llamado como si fuera escrito ahí originalmente, esto hace
que el programa sea mas grande pero se evita el tiempo del llamado a la función haciendo el
programa mas rápido, con la ventaja de tener el código centralizado en una sola parte y con el
chequeo de sintaxis de una función.
Las funciones en línea que contienen ciclos no son expandidas y generalmente el compilador da
una advertencia.
Nota:
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 78
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 86/212
El compilador puede ignorar una declaración “inline”; y también dependiendo de las
optimizaciones que se usen, el compilador puede hacer funciones en línea que no se declararon
como “inline”.
Listado// enlinea.cpp
// funciones en linea
// utiliza una función "inline" para intercambiar dos valores
#include<iostream>
#include <ctime>
using namespace std;
// Las funciones inline (en linea) se expanden donde se llaman
inline void cambia(char &a, char &b) {
char c;
if (rand()%2) {
c = a;
a = b;
b = c;
}
}
void tabs(int n) {
int i;
for (i = 0; i < n; i++)
cout << "\t";
}
int main() {
int i;
char x, y;
x = '#';
y = 'O';
srand( (unsigned)time( NULL ) );
for (i = 0; i < 10; i++) {
tabs(i);
cout << x << endl;
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 79
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 87/212
cambia(x, y);
}
return 0;
}
Salida
#
#
O
O
O
O
O
#
#
#
inline void cambia(char &a, char &b)
La palabra “inline” indica que la función será expandida donde sea llamada.
for (i = 0; i < 10; i++) {tabs(i);
cout << x << endl;
cambia(x, y);
}
Aquí se encuentra la llamada a la función “cambia” y en esta
parte se incluye el código de la función en lugar del código
para llamarla por parte del compilador.
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 80
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 88/212
Capitulo 3Punteros, referencias y arreglos
3.1 CreaciónUn puntero es un a variable que almacena una dirección de memoria. Esta dirección es
usualmente la localidad de otra variable en memoria. Si una variable contiene la dirección de otra
variable, entonces se dice que la primera variable apunta a la segunda.
Los punteros son usados para accesar en forma expedita porciones de memoria.
Pasos a seguir al usar punteros1. Define el puntero (Usando el *)
char *pn;
2. Inicializa el puntero para apuntar a algo (Usando &)
pn = &n;
3. Toma a lo que este apuntando el puntero (Usando *), a este proceso se le llama indirección
cout << “pn esta apuntando a “ << *pn;
Ejemplo:
char c, n, *pn;
n = 'X';
pn = &n;
c = *pn; ( c = 'X')
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 82
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 89/212
fig1. Simplificación de variables en memoria
El operador & solo se puede aplicar a variables y a elementos de un arreglo. Son ilegales
construcciones como:
&(x+1)
&3
Listado
// apunta.cpp// ejemplo de punteros e indireccion
// recomendable analisar la salida al mismo tiempo que el codigo
#include <iostream>
using namespace std;
int main() {
int n;
int *pn;
n = 123;
cout << endl << "n = 123;";
cout << endl << "valor de n=" << n
<< " Direccion de n=" << &n
<< endl;
pn = &n; // pn apunta a n (contiene la direccion de n)
cout << endl << "pn = &n;";
cout << endl << "Valor de pn=" << pn<< " Valor a donde apunta pn=" << *pn
<< endl;
*pn = 321; // se accesa n indirectamente
cout << endl << "*pn = 321;";
cout << endl << "valor de n=" << n
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 83
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 90/212
<< endl;
n++;
cout << endl << "n++;";
cout << endl << "acceso indirecto al valor de *pn="
<< *pn;
return 0;
}
Salida (los valores de las direcciones son dependientes de
la ejecución)
n = 123;
valor de n=123 Direccion de n=0xbfb9aaf8
pn = &n;
Valor de pn=0xbfb9aaf8 Valor a donde apunta pn=123
*pn = 321;
valor de n=321
n++;
acceso indirecto al valor de *pn=322
La salida explica el programa al mostrar los valores, las direcciones de las variables, y como se
asigna estas direcciones a la variable de tipo puntero, además del acceso indirecto que se logra
por medio del puntero.
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 84
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 91/212
3.2 Operaciones con punterosMediante un puntero se puede acceder a diferentes direcciones de memoria siempre y cuando
sea del mismo tipo. Se puede realizar comparaciones entre punteros y hacer restas y sumas a
punteros y entre punteros. Al incrementar o decrementar un puntero, éste apuntara a la posición
de memoria del elemento siguiente o anterior según sea el caso en función de su tipo base.
Ejemplo:
char *pn, n =’X’;
pn = &x;
fig2. Simplificación de memoria, en base a una maquina de 16 bits
pn++;
fig3. Simplificación de memoria, en base a una maquina de 16 bits
Listado
// operap.cpp
// operaciones con punteros
#include <iostream>
using namespace std;
int main() {
char a, b, *pc1, *pc2;
a = 'A';
b = 'B';
pc1 = &a;
cout << "pc1 = &a;" << endl;
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 85
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 92/212
cout << " Acceso indirecto variable \"a\" mediante pc1 "
<< *pc1 << endl;
pc1 = &b;
cout << "pc1 = &b;" << endl;
cout << " Acceso indirecto variable \"b\" mediante pc1 "
<< *pc1 << endl;
pc2 = pc1;
cout << "pc2 = pc1;" << endl;
cout << " Acceso indirecto variable \"b\" mediante pc2 "
<< *pc1 << endl;
if (pc1 == pc2)
cout << "Los dos punteros apuntan a la misma direccion" << endl;
else
cout << "Los dos punteros apuntan a diferentes direcciones" <<
endl;
pc1 = &a;
cout << "pc1 = &a;" << endl;
if (pc1 == pc2)
cout << "Los dos punteros apuntan a la misma direccion" << endl;
else
cout << "Los dos punteros apuntan a diferentes direcciones" <<
endl;
// Se incrementa el contenido de donde apunta pc1
cout << endl << "Valor de donde apunta pc1 = " << *pc1
<< endl << "(Valor de donde apunta pc1) + 1 = "
<< char(*pc1 + 1)
<< endl << "(Valor de donde apunta pc1) + 2 = "<< char(*pc1 + 2) << endl;
return 0;
}
Salida
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 86
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 93/212
pc1 = &a;
Acceso indirecto variable "a" mediante pc1 A
pc1 = &b;
Acceso indirecto variable "b" mediante pc1 B
pc2 = pc1;Acceso indirecto variable "b" mediante pc2 B
Los dos punteros apuntan a la misma direccion
pc1 = &a;
Los dos punteros apuntan a diferentes direcciones
Valor de donde apunta pc1 = A
(Valor de donde apunta pc1) + 1 = B
(Valor de donde apunta pc1) + 2 = C
pc1 = &a;
Se asigna la dirección de la variable “a”.
char(*pc1 + 1)
Incrementa el contenido de donde apunta “pc1”, el valor de la variable “a” es “A” que es 65 en
código ASCII, 65 + 1 = 66 y lo despliega como carácter con la conversión a tipo char().
Nota:
La aritmética de punteros se analiza después de estudiar arreglos, en el siguiente tema.
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 87
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 94/212
Puntero nulo
Un puntero nulo es un puntero que apunta a “NULL”, es decir apunta a una dirección cero, se
dice que es un puntero “0”. El puntero “NULL” no concide con ninguna dirección de variable o
función. Muy útil en manejo de colas, listas, pilas, etc.
Punteros a void
Es aquel que apunta a un tipo “void”. Significa que el puntero no apunta a ningún tipo de valor...
y es más o menos genérico, es decir se puede usar para apuntar a diferentes tipos de memoria.
(Más o menos genérico porque no se permite la asignación de la dirección de una constante o
de punteros a constantes, punteros a miembros de una clase, etc)
Ejemplo:
void *puntero;
Indireccion simple y múltiple
fig4, Simplificación de indireccion
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 88
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 95/212
Ejemplo:
float **n;
Aquí “n” no es un puntero a un numero en punto flotante, sino un puntero aun puntero
“float”.
Listado
// indir_multiple.cpp
// Ejemplo de indireccion multiple
#include <iostream>
using namespace std;
int main() {
int x, *p, **q;
x = 10;
p = &x;
q = &p;
cout << endl << "q=" << q
<< endl << "*q=" << *q
<< endl << "**q=" << **q;
return 0;
}
Salida (Dependiente de la ejecución)
q=0xbfff1f40
*q=0xbfff1f44
**q=10
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 89
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 96/212
Llamada por punteros
En este método, la dirección en memoria del argumento es copiada dentro del argumento de la
función. La dirección es usada para accesar el valor en memoria de la variable usada en la
llamada.
Para usar este método se pasa una dirección de memoria como argumento. Los punteros son
pasados a la función como cualquier otro valor pero declarando los parámetros de tipo
apuntador.
Listado
// cambia.cpp
// intercambia dos numeros con una funcion
#include <iostream>
using namespace std;
void cambia(int *x, int *y) {
int paso;
paso = *x;
*x = *y;
*y = paso;
}
int main() {
int x = 20, y = 10;
cout << "x=" << x << " y=" << y << endl;
cambia(&x, &y);
cout << "x=" << x << " y=" << y;
return 0;
}
Salida
10 20
void cambia(int *x, int *y) {
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 90
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 97/212
Las variables dentro de los paréntesis indican que se va a recibir direcciones, al igual “void”
indica que la función no va a regresar un valor.
cambia(&x, &y);
El símbolo “&” antes del nombre de la variable indica que se manda la dirección de la variable.
Punteros a funciones
Las funciones se encuentran dentro de la memoria de segmento de código, por lo tanto la
dirección de inicio de la función se puede asignar a un puntero.
Teniendo una función:
int nombre_funcion(int char *);
Se declara un puntero a función:
int (*puntero_a_funcion) (int, char *)
Para inicializar el puntero:
puntero_a_funcion = nombre_funcion;
3.3 ReferenciasUna referencia es la asociación de un nombre a un objeto determinado; una referencia es como
un puntero constante al que se le aplica una indirección cada vez que se hace referencia a éste.Es como un puntero porque aloja una dirección y como una variable común porque no se tiene
que usar una notación específica como en el caso de los punteros cuando se usa la variable.
La variable tipo referencia debe inicializarse al momento de declararse.
Listado
// referencias.cpp
// ejemplo de referencias
#include <iostream>
using namespace std;
int main() {
int n = 123;
int &rn = n;
cout << "n=" << n << endl;
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 91
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 98/212
cout << "rn=" << rn << endl << endl;
rn++;
cout << "rn++=" << rn << endl;
cout << "n=" << n << endl << endl;
n++;
cout << "n++=" << n << endl;
cout << "rn=" << rn << endl;
return 0;
}
Salidan=123
rn=123
rn++=124
n=124
n++=125
rn=125
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 92
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 99/212
int &rn = n;
Se declara la variable de referencia “rn”, con el signo “&” antes de la variable y se hace
referencia a la variable “n”.
rn++;Se incrementa indirectamente la variable “n” por medio de la referencia.
cout << "\n rn = " << rn;
Se despliega el valor de “n” por medio de la referencia “rn”.
Llamada por referencia
El argumento de la función es inicializado con la dirección en memoria del argumento, la
referencia es usada para accesar el valor en memoria de la variable usada en la llamada.
Listado
// cambia_rf.cpp
// Usa una funcion que intercambia los valores de sus argumentos
// utilizando paso por Referencia
#include <iostream>
using namespace std;
void cambia(int &a, int &b) {
int paso;
paso = a;
a = b;
b = paso;
}
int main() {
int x, y;
x = 10; y = 20;
cambia(x, y);
cout << endl << "X = " << x;
cout << endl << "Y = " << y;
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 93
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 100/212
return 0;
}
Salida
X = 20 Y = 10
void cambia(int &a, int &b) {
Se declara la función con paso por referencia
cambia(x, y);
Se llama la función. Note que en la llamada no se encuentra
diferencia entre la llamada por valor y la de por
referencia.
3.4 Arreglos unidimensionales, bidimensionales y
multidimensionales
Arreglos unidimensionalesLos arreglos son listas en memoria de variables del mismo tipo reunidas bajo un
mismo nombre; cada variable de la lista puede ser accesada individualmente
mediante un número el cual corresponde al orden en que son almacenadas, a
este número se le llama índice.
Forma general:
tipo nombre_variable[tamaño]
En C++ todos los arreglos usan el cero como índice del primer elemento.
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 94
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 101/212
Ejemplo:
int lista[3];
Declara un arreglo llamado lista con tres elementos desde “lista[0]” hasta “lista[2]”.
Listado
// fecha.cpp
// elementos del arreglo accesados fuera de un ciclo
#include <iostream>
using namespace std;
int main() {
int fecha[3];
fecha[0] = 1; // mes
fecha[1] = 1; // dia
fecha[2] = 2010; // aa
cout << "Fecha ";
cout << fecha[0] << '/' << fecha[1] << '/' << fecha[2];
return 0;
}
Salida
Fecha 1/1/2010
int fecha[3];Se declara un arreglo de enteros de tres elementos.
fecha[0] = 1;
fecha[1] = 1;
fecha[2] = 2010;
Se le asigna valores al arreglo elemento por elemento.
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 95
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 102/212
Ejercicio
1. Modifique el ejemplo anterior (fecha.cpp) para que lea la fecha del teclado.
Listado
// ordena_c.cpp
// Lee un arreglo de enteros y ordena los elementos de mayor a menor
#include <iostream>
using namespace std;
const int TAM = 3;
int main() {
int iCalificacion[TAM], iCalifTemp;int i, j;
cout << "Ingresa calificaciones" << endl;
for (i = 0; i < TAM; i++) {
cout << "Calificacion " << i << "? ";
cin >> iCalificacion[i];
}
// Ordena califcaciones en base a la califiacion de mayor a menorfor (i = 0; i < TAM; i++)
for (j = 0; j < TAM; j++) {
// ordena de mayor a menor
if (iCalificacion[i] > iCalificacion[j]) {
// intercambia la califcacion
iCalifTemp = iCalificacion[i];
iCalificacion[i] = iCalificacion[j];
iCalificacion[j] = iCalifTemp;
}}
cout << endl << "Calificaciones de mayor a menor: " << endl;
for (i = 0; i < TAM; i++)
cout << iCalificacion[i] << endl;
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 96
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 103/212
return 0;
}
Salida en base a la entrada de ejemplo
Ingresa calificacionesCalificacion 0? 100
Calificacion 1? 90
Calificacion 2? 95
Calificaciones de mayor a menor:
100
95
90
const int TAM=3;
Declara una constante de tipo entero, es decir un almacenamiento con el nombre “TAM” el cual
no puede ser cambiado durante la ejecución del programa.
for (i = 0; i < TAM; i++) {
cout << "Calificacion " << i << "? ";
cin >> iCalificacion[i];
}
Se llena el arreglo dentro del ciclo “for”.
for (i = 0; i < TAM; i++)
for (j = 0; j < TAM; j++) {
// ordena de mayor a menor
if (iCalificacion[i] > iCalificacion[j]) {
// intercambia la califcacion
iCalifTemp = iCalificacion[i];
iCalificacion[i] = iCalificacion[j];iCalificacion[j] = iCalifTemp;
}
}
En estas líneas el arreglo es ordenado en base al valor mayor.
El ordenamiento del arreglo se realiza al comparar el primer elemento del arreglo con todos los
demás y si se cumple la condición, el elemento que es comparado con todos se intercambia, el
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 97
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 104/212
segundo con todos y así sucesivamente, en este algoritmo el ciclo interno es el que controla el
ordenamiento, en este caso moviendo el mayor hacia el primer elemento del arreglo.
Ejemplo 1:
Ingresa calificaciones
Calificacion 0? 1
Calificacion 1? 4
Calificacion 2? 7
Calificaciones de mayor a
menor:
7
4
1
Primera pasada:
1 4 7
1 4 7
Segunda pasada:
1 4 7
4 1 7
Tercera pasada:
4 1 7
7 4 1
Ejemplo 2:Ingresa calificaciones
Calificacion 0? 4
Calificacion 1? 1
Calificacion 2? 7
Calificaciones de mayor a menor:
1
4
7
Primera pasada:
4 1 7
1 4 7
Segunda pasada:
1 4 7
1 4 7
Tercera pasada:
1 4 7
1 4 7
Este método de ordenamiento es fácil de implementar, pero definitivamente no es el más
eficiente, se puede observar que se pierden ciclos al repetir las comparaciones y redundar el
ordenamiento. Se puede optimizar al pasar el control del ordenamiento al primer ciclo haciendo
lo siguiente:
for (i = 0; i < TAM; i++)
for (j = i+1; j < TAM; j++) {
if (iCalificacion[i] < iCalificacion[j]) {
iCalifTemp = iCalificacion[i];
iCalificacion[i] = iCalificacion[j];
iCalificacion[j] = iCalifTemp;
}
}
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 98
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 105/212
Note que se asigna a la variable de control del ciclo interno el valor de la variable de control del
ciclo externo mas uno, para no repetir la comparación, también se cambia la condición de mayor
que a menor que.
Ejercicios
1. Modifique el ejemplo anterior (ordena_c.cpp) para que ordene el arreglo de menor 2. Realice
un programa que
a) Pida diez números enteros y los almacene en un arreglo
b) Busque el número menor y el número mayor en el arreglo leído
c) Despliegue el número menor y el número mayor
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 99
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 106/212
Comprobación de contornos
El lenguaje C++ no realiza comprobación de contornos en los arreglos. Si se sobrepasa el final
durante una operación de asignación, entonces se asignarán valores a otras variables en
memoria o memoria usada por el propio código del programa, lo que puede provocar resultados
no deseados, o un error que detiene la ejecución del programa. Las comprobaciones son
responsabilidad del programador.
Listado
// for_out.cpp
// Programa que sobrepasa el limite de indexacion
#include <iostream>
using namespace std;
int main() {
int lista[10], i;
for (i = 0; i < 100; i++) {
lista[i] = i;
cout << lista[i] << ' ';
}
return 0;
}
Salida (depende de la ejecución, puede marcar errores de memoria y no haber salida)
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
31 32 33 34 35 36 37 38
Nota:
Este programa compilará bien. Y sirve de ejemplo para la comprobación de los límites del
arreglo.
Arreglos bidimensionales y multidimensionales
Los arreglos multidimensionales son arreglos con más de un índice, por ejemplo
los bidimensionales son arreglos con dos subíndices que son usados para
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 100
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 107/212
representar tablas de valores, con información organizada en reglones y
columnas. Para accesar un elemento particular de la tabla hay que identificar el
renglón del elemento seguido por la columna.
Forma general:
tipo nombre[longitud_1][longitud_2]
Ejemplo:
int matriz[3][2];
Declara un arreglo 3 x 2 llamado matriz con seis elementos desde “matriz[0][0]” hasta
“matriz[2][1]”.
Listado
// sumamat.cpp
// Suma dos matrices dejando el resultado en una tercera
#include <iostream>
using namespace std;
const int LON = 2;
int main(){
int i, j, a[LON][LON], b[LON][LON], c[LON][LON];
cout << "Ingresa la matriz A " << endl;
for (i=0; i < LON; i++)
for (j=0; j < LON; j++) {
cout << "A[" << i << "][" << j << " ] = ? ";
cin >> a[i][j];
}
cout << endl << "Ingresa la matriz B " << endl;
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 101
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 108/212
for (i=0; i < LON; i++)
for (j=0; j < LON; j++) {
cout << "B[" << i << "][" << j << " ] = ? ";
cin >> b[i][j];
}
// Suma las matrices y deja el resultado en una tercera matriz
for (i=0; i < LON; i++)
for (j=0; j < LON; j++)
c[i][j] = a[i][j] + b[i][j];
cout << endl << "El resultado de la suma de A + B es:" << endl;
for (i=0; i < LON; i++) {
for (j=0; j < LON; j++)
cout << c[i][j] << "\t";
cout << endl;
}
return 0;
}
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 102
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 109/212
Salida en base a la entrada de ejemplo
Ingresa la matriz A
A[0][0 ] = ? 1
A[0][1 ] = ? 1
A[1][0 ] = ? 1A[1][1 ] = ? 1
Ingresa la matriz B
B[0][0 ] = ? 2
B[0][1 ] = ? 2
B[1][0 ] = ? 2
B[1][1 ] = ? 2
El resultado de la suma de A + B es:
3 3
3 3
int i, j, a[LON][LON], b[LON][LON], c[LON][LON];
Se declaran las variables a ser usadas, “i” y “j” para usarlas como subíndices y tres arreglos de
dos dimensiones.
for (i=0; i < LON; i++)
for (j=0; j < LON; j++) {
cout << "A[" << i << "][" << j << " ] = ? ";
cin >> a[i][j];
}
Se usan dos “for”, el primero para accesar los renglones y el segundo que está dentro del cuerpo
del primer “for” para accesar las columnas.
1 for (i=0; i < LON; i++)
2 for (j=0; j < LON; j++)
3 c[i][j] = a[i][j] + b[i][j];
Se suman los dos arreglos dejando el resultado en el tercer arreglo.
Ejercicio
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 103
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 110/212
1 Realice un programa que pida un arreglo de 3x3 y sume la diagonal principal, despliegue la
suma.
Arreglos de más de dos dimensionesUn arreglo de enteros de tres dimensiones de 2 x 2 x 2 se declararía de la siguiente manera:
int cubo[2][2][2];
Para acceder el primer elemento seria:
cubo[0][0][0] = 0; //asigna cero al primer elemento del arreglo tridimensional
Para un arreglo de enteros de cuatro dimensiones de 2 x 2 x 2x2 se declararía de la siguiente
manera:
int cuatridimensional[2][2][2][2];
Para acceder el primer elemento seria:
cuatridimensional [0][0][0][0] = 0; //asigna cero al primer elemento del arreglo
Este tipo de arreglos son raramente usados ya que aumenta la complejidad del programa y
generalmente la solución del problema se pude replantear para evitar complejidades
innecesarias, en caso de que sea inevitable siempre se puede usar este tipo de arreglos.
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 104
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 111/212
Arreglos y punteros
Cuando se declara un arreglo el compilador debe asignar una dirección base y la cantidad de
almacenamiento suficiente para alojar a todos los elementos del arreglo. Los punteros y arreglos
se utilizan casi de la misma manera para acceder a la memoria.
Nota
El nombre de un arreglo es una constante que contiene la dirección del inicio del arreglo también
llamado puntero fijo y un puntero es una variable cuyos valores son direcciones.
Listado
// a_apunta.cpp
// Relacion entre arreglos y punteros
#include <iostream>
using namespace std;
int main(){
char cstr1[] = "ARREGLO";
char cstr2[] = "PUNTERO";
char *pc;
cout << "cstr1: " << cstr1 << endl;
cout << "cstr2: " << cstr2 << endl;
pc = cstr1;
cout << "\npc: " << pc;
pc = cstr2;
cout << "\npc: " << pc;
return 0;
}
Salida en base a la entrada de ejemplo
cstr1: ARREGLO
cstr2: PUNTERO
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 105
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 112/212
pc: ARREGLO
pc: PUNTERO
char cstr1[] = "ARREGLO";char cstr2[] = "PUNTERO";
Se declaran dos arreglos de caracteres y se inicializan,.
char *pc;
Se declara la variable de tipo puntero.
cout << "cstr1: " << cstr1 << endl;
cout << "cstr2: " << cstr2 << endl;
Se despliega el contenido de cstr1 y cstr2, (líneas 11 y 12).
pc = cstr1;
Se asigna la dirección de la cadena de caracteres y en la siguiente línea se despliega el
contenido de “cstr1” por medio del puntero “pc”.
3.5 Cadenas de caracteresUna cadena de caracteres consiste en un arreglo de caracteres terminado en un nulo. Un nulo
se especifica como '\0'. Si se quiere definir una cadena de 5 elementos se debe definir de 6 para
soportar el carácter nulo.
Ejemplo:
char str[6];
Una constante de cadena es una lista de caracteres que se encierran entre comillas.
Ejemplo:
"HOLA"
Al declarar una constante de cadena el compilador de C++ agregara automáticamente elcarácter nulo al final.
La cadena "HOLA" se vera en memoria así:
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 106
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 113/212
Listado
// cadena.cpp// Cadenas de caracteres
#include <iostream>
using namespace std;
int main() {
char s[16];
char s2[] = {'h', 'o', 'l', 'a', '\0'};
char s3[] = "HOLA A TODOS";
cout << endl << "Ingresa una cadena de caracteres ";
// El "cin" por si solo, deja de leer cuando encuentra
// un espacio
cin.getline(s, 15); // para incluir espacios en la cadena
cout << "s=" << s << endl
<< "s2=" << s2 << endl
<< "s3=" << s3 << endl;
s3[5] = '\0';
cout << "s3=" << s3 << endl;
return 0;
}
Salida en base a la entrada de ejemplo
Ingresa una cadena de caracteres Issac Asimov
s=Issac Asimov
s2=hola
s3=HOLA A TODOS
s3=HOLA
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 107
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 114/212
char s[16];
Declara un arreglo de caracteres.
char s2[] = {'h', 'o', 'l', 'a', '\0'};
Se declara un arreglo de caracteres y se inicializa, este tipo de inicialización en arreglos solo es
permitido al momento de declarar el arreglo.
La asignación del elemento '\0' al final del arreglo es para tratar el arreglo como una cadena de
caracteres. Hay que notar que no se indica cuantos elementos tiene el arreglo; como se está
inicializando se deja la cantidad fuera de la declaración para que el compilador incluya la
cantidad en “s2[]”.
char s3[] = "HOLA A TODOS";
Se declara un arreglo de caracteres y se inicializa con una cadena de caracteres. Al hacer la
inicialización de esta forma, el compilador incluye además de la cantidad de elementos en “s3[]”
el carácter “\0” al final, este tipo de inicialización en arreglos solo es permitido al momento de
declarar el arreglo.
La cadena s3 se vería en memoria así:
s3[5] = '\0';
Se asigna el carácter nulo en el quinto elemento, por lo tanto:
La cadena s3 se vería en memoria así:
cout << s3 << endl;
Despliega la cadena “s3”, siendo la salida “HOLA ”, porque el “cout” se detiene al encontrar el
primer carácter '\0' que es el que indica el fin de cadena.
Listado
// mayusculas.cpp
// Convierte una cadena de caracteres a mayusculas
#include <iostream>
using namespace std;
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 108
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 115/212
char mensaje[80];
void mayusculas(void) {
int i;
for (i = 0; mensaje[i] != '\0'; i++)
mensaje[i] = toupper(mensaje[i]);
}
main() {
cout << "\Ingresa un mensaje ";
cin.getline(mensaje, 79);
mayusculas();
cout << "\nEl mensaje en mayusculas es " << mensaje;
}
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 109
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 116/212
Salida
Ingresa un mensaje issac asimov
El mensaje en mayusculas es ISSAC ASIMOV
char mensaje[80];
Se declara una cadena de caracteres global para las
funciones que están abajo de ésta.
void mayusculas(void) {
El primer “void” significa que la función no regresa nada,
actúa como un procedimiento. “mayusculas” es el nombre de la
función y “void” dentro de los paréntesis significa que la
función no recibe parámetros.
En el cuerpo de la función se convierte cada elemento de la
cadena de caracteres a mayúsculas.
mayusculas();
Manda llamar la función.
Ejercicios
1. Realice un programa que ingrese y despliegue una cadena de caracteres elemento por
elemento.
2. Hacer un programa que lea y almacene una cadena caracteres con un máximo de 80
caracteres y despliegue la cadena en mayúsculas, investigue el uso de la función toupper ()
(#include <ctype>)
3. Hacer un programa que lea y almacene una cadena caracteres con un máximo de 80
caracteres y despliegue la cadena en orden inverso, recuerde que el carácter nulo ‘\0’ indica
el fin del texto.
Apuntadores a caracteres
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 110
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 117/212
Si se declara mensaje como:
char *mensaje;
La sentencia:
mensaje = "esta es una cadena"
Asigna a mensaje un apuntador a los caracteres. No es la copia de una cadena.
Listado
// strlen_punteros.cpp
// Ejemplo de como puede estar implementada la funcion de la
// biblioteca estandard strlen (implementada usando apuntadores)
int strlen(char *s) {
char *p = s;
while (*p != '\0')
p++;
return p-s;
}
Ejercicios
1. Analice como es que la función cuenta el número de caracteres contenidos en la cadena
2. Implemente la función “main” para probar la función
Listado
// copia_cadena.cpp
// Copia origen a destino usando apuntadores
#include <iostream>
using namespace std;
void copia_cadena(char *destino, char *origen) {
do {
*destino = *origen;
destino++;
origen++;
} while(*origen != '\0');
*destino = *origen; // copia el caracter '\0'
}
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 111
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 118/212
int main(){
char str1[80], str2[80];
cout << "Ingresa un string ";
cin.getline(str1, 79);
copia_cadena(str2, str1);
cout << str2 << endl;
return 0;
}
Salida en base a la entrada de ejemplo
Ingresa un string Bjarne Stroustrup
Bjarne Stroustrup
Ejercicio
1. Escriba una función str_busca(str, c) que reciba un apuntador a una cadena de caracteres
str, y un carácter c. Busque el carácter en la cadena y regrese la posición en que se
encuentra el carácter en la cadena o un -1 si no se encuentra utilizando apuntadores.2. Realice una función concatena(str1, str2) que agregue la cadena de caracteres str2 al final
de la cadena str1.
3. Realice una función reversa(str) que reciba un apuntador a una cadena de caracteres e
invierta la cadena. Utilizando apuntadores.
Aritmética de punteros
Ejemplo:
Teniendo:int n[3] = {1, 2, 3}, *p;
Las siguientes sentencias son equivalentes; ambas asignan la dirección de inicio del
arreglo al puntero p.
p = n;
p = &n[0];
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 112
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 119/212
fig5. Simplificación de memoria, maquina de 16 bits
Las siguientes sentencias son equivalentes; ambas asignan la dirección de memoria del
segundo elemento al puntero p.
p = n + 1;
p = &n[1];
fig6. Simplificación de memoria, maquina de 16 bits
Las siguientes sentencias son equivalentes para accesar el contenido de un elemento:
n[i];
*(p+i)
Las siguientes sentencias son equivalentes para accesar la dirección de un elemento:&n[i];
n+i;
Un apuntador es una variable, por lo que son correctas las siguientes operaciones:
p = n;
p++;
El nombre de un arreglo es una constante; así que son ilegales construcciones como:
n = p;n++;
p = &n;
n = n + 2;
Listado
// aritmetica_puntero.cpp
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 113
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 120/212
// Aritmetica de punteros
#include <iostream>
using namespace std;
int main() {
char *p, s[] = "ABCDEFG";
p = s;
// despliega la cadena a traves del puntero
cout << endl << p // toda la cadena
<< endl << p[0] // un elemento, el primero
<< endl << *(p+1) // un elemento, el segundo
<< endl << p+2; // a partir del tercer elemento
return 0;
}
Salida
ABCDEFG
A
B
CDEFG
char *p, s[] = "ABCDEFG";
Se declara un carácter, una cadena de caracteres y un puntero a caracteres, que se utiliza para
accesar el contenido de la cadena y del carácter en el resto del programa.
p = s;
Se asigna la dirección de s al puntero p.
cout << endl << p[0]
Despliega el primer elemento de la cadena s indirectamente, esto es equivalente a decir *p, el
contenido de donde apunta p.
<< endl << *(p+1)
Despliega, el contenido del segundo elemento de s, esto es equivalente a p[1], aquí se realiza
primero la operación de lo que esta entre paréntesis, se incrementa la dirección del puntero y
después accesa el contenido de la dirección que contiene p después de la suma *(p+1).
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 114
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 121/212
<< endl << p+1;
Incrementa el contenido de la variable (en una dirección –note que esto solo es temporalmente)
y despliega la cadena a partir de la dirección del elemento 2, como se muestra.
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 115
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 122/212
3.6 Asignación dinámica de memoriaManejar la memoria dinámicamente es útil cuando no se sabe la cantidad o el tipo de objeto
hasta que el programa está en ejecución, o cuando se quiere que los objetos no estén sujetos a
las reglas normales de alcance definidas por el lenguaje.
Normalmente se definen y se usan los objetos en tiempo de compilación, el manejo dinámico de
la memoria libera de la limitante de saber todo al tiempo de compilación, permitiendo crear y
destruir objetos en tiempo de ejecución.
new
Aloja memoria dinámicamente, regresa un apuntador a la memoria alojada. Si falla resulta una
excepción “bad_alloc”.
Ejemplo:
int *n;n = new int;
Aloja memoria suficiente para almacenar un entero.
delete
Desaloja un bloque de memoria dinámica que ha sido previamente alojado por el operador
“new”. El desalojo de memoria la libera para su reutilización.
Ejemplo:
int *n;n = new int;
delete n;
Desaloja la memoria que fue separada por “new” y asigna un nulo al puntero.
Listado
// new_del.cpp
// ejemplo de manejo dinámico de memoria// Operadores new y delete con un arreglo
#include <iostream>
using namespace std;
int main() {
int *ca;
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 116
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 123/212
ca = new int[3]; // Toma memoria para el arreglo
ca[0] = 8;
ca[1] = 21;
ca[2] = 2020;
cout << "Fecha ";
cout << ca[0] << '/' << ca[1] << '/' << ca[2];
delete []ca; // Regresa la memoria al almacenamiento libre
return 0;
}
Salida
Fecha 8/21/2020
int *ca;
Se declara un puntero a enteros.
ca = new int[3];
“new”, separa memoria necesaria para almacenar 3 enteros y le asigna la dirección de inicio del
bloque de memoria separado.
En el programa se trata el bloque como un arreglo normal (los arreglos y el manejo de punteros
esta íntimamente ligado) y se le asigna enteros a cada elemento.
delete []ca;
Se libera el bloque de memoria separado anteriormente con el operador “new”.
Listado
// asientos.cpp
// anejo dinámico de memoria utilizando un arreglo de strings,
// el programa administra un lugar con asientos numerados.
#include <iostream>
#include <string>
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 117
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 124/212
using namespace std;
int main() {
int total_asientos, numero, i;
string *asiento;
cout << "\nCantidad de asientos con que cuenta el local? ";
cin >> total_asientos; // Toma la longitud del arreglo
asiento = new string[total_asientos]; // Aloja el arreglo
do {
for (i=0; i < total_asientos; i++)
cout << endl << "Asiento " << i
<< ": " << asiento[i];
cout << endl << "Numero de Asiento? (-1 termina)";
cin >> numero;
if (numero < 0)
break;
cout << "Nombre ";
cin >> asiento[numero];
} while(1);
delete []asiento;
return 0;
}
Salida en base a la entrada de ejemploCantidad de asientos con que cuenta el local? 3
Asiento 0:
Asiento 1:
Asiento 2:
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 118
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 125/212
Numero de Asiento? (-1 termina)1
Nombre Batman
Asiento 0:
Asiento 1: BatmanAsiento 2:
Numero de Asiento? (-1 termina)0
Nombre Superman
Asiento 0: Superman
Asiento 1: Batman
Asiento 2:
Numero de Asiento? (-1 termina)
string *asiento;
Se declara un puntero a string
asiento = new string[total_asientos];
Se crea un bloque de memoria suficiente para almacenar el número asignado a la variable
“total_asientos”.
El resto del programa muestra los elementos y se accesa el elemento seleccionado por elusuario, en caso de que el numero sea -1 se cumple la condición del “if” y se ejecuta la
instrucción “break” que termina el ciclo “do .. while”
delete []asiento;
“delete”, regresa el bloque de memoria al almacenamiento libre.
Ejercicio
Modifique el programa ordena_c.cpp para que pida la cantidad
de calificaciones al momento de ejecución, es decir cree el
arreglo dinámicamente
Punteros a estructuras y manejo de memoria dinámica
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 119
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 126/212
El uso de punteros es para generar llamadas por referencia al llamar una función, para crear
listas encadenadas así como estructuras dinámicas de datos.
Cuando un puntero a estructura es pasado a una función, solo la dirección de la estructura es
puesta en el stack de datos. Esto permite unas llamadas muy rápidas a las funciones.
Ejemplo:
struct bal {
float balance;
char nombre[40];
} persona;
Declarando un apuntador a estructura.
struct bal *p;
Esto pone la dirección de la estructura persona en el apuntador p:
p = &persona;
Para accesar los elementos de la estructura usando un apuntador a esa estructura, usamos:
(*p).balance;
Los paréntesis son necesarios alrededor del apuntador porque el operador punto (.) tiene mayor
prioridad mayor que el operador *.
El segundo método de acceso es utilizando el operador ->; lo cual nos facilita la programación.
Ejemplo:
p->balance;
Para usar asignar memoria dinámica usamos el operador “new”.
Ejemplo:
p = new bal;
Listado
// newstruct.cpp
// ejemplo del manejo de memoria dinamica con estructuras.
// Los operadores new y delete
#include <iostream>
using namespace std;
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 120
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 127/212
struct Fecha {
int mes;
int dia;
int ayo;
};
int main() {
Fecha *fecha = new Fecha; // Toma memoria para una fecha
fecha->mes = 3;
fecha->dia = 30;
fecha->ayo = 1968;
cout << "\nFecha: "
<< fecha->mes << '/'
<< fecha->dia << '/'
<< fecha->ayo;
delete fecha; // Regresa la memoria al almacenamiento libre
return 0;
}
Salida
Fecha: 3/30/1968
Fecha *fecha = new Fecha;
Se declara el puntero de tipo estructura “Fecha”, y se
inicializa con la dirección de inicio del bloque de memoria
alojado con el operador “new”.
Operador ->
fecha->mes = 3;
Es equivalente a:
(*fecha).mes
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 121
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 128/212
los paréntesis son necesarios ya que el punto (.) tiene
mayor procedencia que el asterisco (*) y sin ellos la
expresión:
*fecha.mes
Significa:
(*fecha.mes)
Lo cual es ilegal porque “mes” no es un puntero.
Nota:
El operado “->” se implemento ya que los punteros a
estructuras son bastante comunes.
Arreglo de punteros y manejo de memoria dinámica
Los apuntadores son variables, así que los podemos almacenar en un arreglo.
Declaración:int *x[10];
Asignación:
x[2] = &v;
Encontrar el valor de v.
*x[2]
Diferencias de arreglos bidimensionales y arreglos de punterosEjemplo sin punteros:
char cap[3][32] = {
"introduccion",
"tipos, operadores y expresiones",
"control de flujo" // No se pone coma
};
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 122
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 129/212
introduccion\0tipos, operadores y expresiones\0control de flujo\0
Se separan 96 bytes de almacenamiento, siempre, sin importar si se usan o no.
Ejemplo con punteros:
char *cap[3] = {
"introduccion",
"tipos, operadores y expresiones",
"control de flujo"
};
2000 3000 3000 introduccion\02000 3001 3001 tipos, operadores y expresiones\0
2002 3002 3002 control de flujo\0
Se separa solo 63 bytes de almacenamiento + 6 bytes para el almacenamiento de los
punteros, es decir solo el espacio estrictamente requerido.
Listado
// nombres.cpp
// Manejo de memoria dinamica, arreglo de punteros
#include <iostream>
using namespace std;
const int LIMITE=5;
int main() {
char str[80], *nombre[LIMITE];
int i;
cout << "Ingresa una lista de nombres" << endl;
for (i=0; i < LIMITE; i++) {
cout << i << ".-Nombre ? ";
cin.getline(str, 79);
// Asigna memoria al elemento i del arreglo nombre
nombre[i] = new char[strlen(str)+1];
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 123
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 130/212
strcpy(nombre[i], str); // Copia str a nombre
}
cout << endl << "Lista de nombres:" << endl;
for (i=0; i < LIMITE; i++)
cout << i << ".- " << nombre[i] << endl;
// desaloja la memoria
for (i=0; i < LIMITE; i++)
delete nombre[i];
return 0;
}
Salida en base a la entrada de ejemplo
Ingresa una lista de nombres
0.-Nombre ? Stroustrup
1.-Nombre ? Abrash
2.-Nombre ? Lamothe
3.-Nombre ? Schildt
4.-Nombre ? Kernighan
Lista de nombres:
0.- Stroustrup
1.- Abrash
2.- Lamothe
3.- Schildt
4.- Kernighan
Ejemplo de Asignación de memoria dinámica con punteros a punteros
Listado
// punteros_punteros.cpp
// manejo de memoria dinamica, punteros a punteros
// Modificacion del programa nombres.cpp
#include <iostream>
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 124
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 131/212
using namespace std;
int main() {
char str[80], **nombre;
int i, n;
cout << endl << "Cantidad de elementos en la lista ? ";
cin >> n;
// Desecha el ultimo caracter del buffer de entrada
// en este caso el caracter nueva linea: '\n'
cin.ignore();
nombre = new char *[n];
cout << endl << "Ingresa una lista de nombres";
for (i=0; i < n; i++) {
cout << endl << i << ".-Nombre? ";
cin.getline(str, 79);
// Asigna memoria a nombre
nombre[i] = new char[strlen(str)+1];
// Copia str a nombre
strcpy(nombre[i], str);
}
cout << endl << "lista de nombres";
for (i=0; i < n; i++)
cout << endl << i << ".-Nombre? " << nombre[i];
// desaloja la memoria de cada elemento
for (i=0; i < n; i++)delete nombre[i];
// Desaloja el total de elementos
delete nombre;
return 0;
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 125
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 132/212
}
Salida en base a la entrada de ejemplo
Cantidad de elementos en la lista ? 3
Ingresa una lista de nombres
0.-Nombre? Bill Watterson
1.-Nombre? Charles M. Schulz
2.-Nombre? Jim Davis
lista de nombres
0.-Nombre? Bill Watterson1.-Nombre? Charles M. Schulz
2.-Nombre? Jim Davis
Argumentos para “main”
Algunas veces es necesario pasar información al programa cuando antes de ejecutarse; esta
información se pasa a la función “main” vía la línea de argumentos.
Argumentos en la línea de comandos
Es la información que sigue incluyendo el nombre del programa en la línea de comandos del
sistema operativo separada por espacios.
Cuando se invoca a “main” al comienzo de la ejecución se llama con dos argumentos llamados
por costumbre: “argc” y “argv”.
argc
Contiene el número de argumentos que están presentes en la línea de comandos cuando seinvoco el programa.
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 126
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 133/212
argv
Variable tipo puntero que contiene la dirección al inicio de un arreglo de cadenas de caracteres.
Este arreglo contienen los argumentos donde cada cadena contiene un argumento.
Ejemplo:
1.- Hacer ejecutable el programa llamado arg.exe por ejemplo.
2.- Ejecutarlo: arg buenos días
Nota:
Es un arreglo de apuntadores. “argc” siempre será 1 porque el primer argumento es el nombre
del programa (algunos sistemas operativos incluyen el “path”).
Listado
// args.cpp// argumentos en la linea de comandos
#include <iostream>
using namespace std;
int main(int argc, char *argv[]) {
int i;
cout << "Numero de Argumentos " << argc;
for (i = 0; i < argc; i++)cout << endl << i << " - " << argv[i];
return 0;
}
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 127
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 134/212
Salida
Numero de Argumentos 4
0 - args
1 - uno
2 - 2
3 - tres
3.7 Uso de clases predefinidas para arreglosClase vector
Útil para trabajar con cierta cantidad de datos desconocidos y arreglos, pues permite manejar
dinámicamente objetos en dichos arreglos, pudiendo crearlos de clases y variables expandiendo
o contrayendo el arreglo. Se encuentra definida en el archivo de encabezado “vector”
Listado
// vector.cpp
// ejemplo de la clase vector
#include <vector>
#include <iostream>
using namespace std;
int main() {
//Declara un vector simple
vector<int> enteros;
int i, num;
cout << "Ingresa un numero: ";
cin >> num;
// agrega un elemento al final del vector
enteros.push_back(num);
// accede a una posicion del vector y se muestra su longuitud
cout << endl << "En la posicion 0 esta: " << enteros[0]
<< endl << "Longitud del vector : " << enteros.size()
<< endl << "Capacidad del vector : " << enteros.capacity()
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 128
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 135/212
<< endl << "Longitud maxima del vector: "
<< enteros.max_size();
// vacia el vector
enteros.clear();
// agrega 10 elementos al vector
for (i=1; i <=10; i++)
enteros.push_back(i);
for (i=0; i < 10; i++)
cout << endl << enteros[i];
cout << endl << "Ahora hay en el vector: "
<< enteros.size() << " elementos\n";
//Elimina el ultimo elemento del vector
enteros.pop_back();
cout << endl << "Hay en el vector: "
<< enteros.size() << " elementos\n";
return 0;
}
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 129
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 136/212
Salida
Ingresa un numero: 55
En la posicion 0 esta: 55
Longitud del vector : 1Capacidad del vector : 1
Longitud maxima del vector: 1073741823
1
2
3
4
5
6
7
8
9
10
Ahora hay en el vector: 10 elementos
Hay en el vector: 9 elementos
Ejercicio
1. Modifique el ejemplo de la pagina 89 (fecha.cpp) para que use la clase vector en vez de un
arreglo.
2. Modifique el ejemplo de la pagina 90 (ordena_c.cpp) para que use la clase vector en vez de
un arreglo.
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 130
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 137/212
Capitulo 4Clases y objetos
4.1 Definición de una claseUna clase es un método lógico de organizar datos y funciones en una misma estructura. La clase
es un patrón a seguir al crear objetos.
Al definir una clase se define un tipo de dato definido por el usuario, y este tipo sirve para crear
instancias de este tipo de dato, a estas instancias se le llama objetos.
La definición de clase es el proceso de definir cuales serán sus propiedades y métodos; proceso
que crea un nuevo tipo de dato.
4.2 Declaración de clasesLa declaración de clase es la asignación de un nombre; una sentencia que establece la
conexión entre el identificador y el objeto que representa (en este caso una clase). La
declaración asocia el nombre con un tipo de dato, lo que supone definir como se usa, que
operaciones son permitidas y que sentido tienen estas operaciones.
Ejemplo:
class mi_clase;
Con frecuencia la declaración y definición de una clase ocurren simultáneamente en la misma
sentencia, igual que con las variables normales,
Forma general:
class nombre_de_la_clase {
etiqueta_de_nivel_de_permiso_1:
miembros1;
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 132
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 138/212
etiqueta_de_nivel_de_permiso_2:
miembros2;
...
} nombre_del_objeto;
4.3 Miembros de una claseTodo lo que esta definido dentro de la clase se dice que es miembro de ésta, como variables,
arreglos, funciones etc.
Las etiqueta_de_nivel_de_permiso se refieren al control de acceso a miembros del objeto. Por
defecto los miembros de una clase son privados.
4.4 Ambito referente a una claseUna 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 accesoprivate
Los miembros que le siguen a esta palabra reservada solo pueden ser accesados por lasfunciones miembro declaradas dentro de la misma clase.
protected
Los miembros que le siguen a esta palabra reservada solo pueden ser accesados por las
funciones miembro dentro de la misma clase, y por las funciones miembro de las clases que son
derivadas de esta clase.
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 133
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 139/212
public
Los miembros que le siguen a esta palabra reservada pueden ser accesados en cualquier lugar
dentro del alcance de la clase.
La funcionalidad que brinda el control de acceso “protected” es usada principalmente cuando se
prevé que la clase creada va a ser heredada; este tipo de acceso se cubre en el capitulo de
herencia.
La funciones están implementadas dentro de la definición de
la clase, si cumplen con las especificaciones de una función
“inline” el compilador las implementa como tales (ver
capitulo de subprogramas).
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 134
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 140/212
4.6 Creación de objetosUn objeto es una instancia de una clase, la clase es el tipo de dato y el objeto es la variable.
Cuando un objeto de la clase es creado, este tendrá su propia copia de las variables miembros
que contiene la clase.
En el siguiente ejemplo se crea una clase para derivar un objeto para representar un emoticon.
Los emoticones son una secuencia de caracteres comúnmente utilizados en la transmisión de
texto mediante correo electrónico, estas secuencias representan una abreviación de palabras y/o
emociones, como por ejemplo “:)” significa sonreír; “:-D” reír a carcajadas, etc.
Listado
// emoticon.cpp
#include <iostream>
#include <string>
using namespace std;
class CEmoticon {
private:
string m_sIcon;
public:
void Muestra(void){
cout << "\n" << m_sIcon;
}
void Apariencia(string a_sIcon){
m_sIcon = a_sIcon;
}
};
int main(){
CEmoticon objeto_icon1; // Declara un objeto de tipo CEmoticon
CEmoticon objeto_icon2;
objeto_icon1.Apariencia(":O");
objeto_icon2.Apariencia(":]");
objeto_icon1.Muestra();
objeto_icon2.Muestra();
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 135
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 141/212
cout << endl;
objeto_icon1.Apariencia(":)");
objeto_icon1.Muestra();
objeto_icon2.Muestra();
return 0;
}
Salida
:O
:]
:)
:]
class CEmoticon {
Se declara la clase “CEmoticon” usando la palabra reservada “class” seguida del nombre de la
clase.
private:
string m_sIcon;
La palabra “private” específica que todos los miembros que le siguen hasta que se encuentre
con otro especificador o el fin de la clase, solo podrán ser accesados por otros miembros de
esta clase, en este caso “m_sIcon” que es de tipo “string”.
public:
void Muestra(void){
cout << "\n" << m_sIcon;
}
void Apariencia(string a_sIcon){
m_sIcon = a_sIcon;
}
Se declaran los miembros que pueden ser accesados en cualquier parte donde se este usando
una instancia de esta clase (objeto).
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 136
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 142/212
La función miembro “Muestra()” es usada para desplegar el contenido de la variable privada
“m_sIcon” y la función Apariencia() para cambiar el valor de esta variable.
Nota:
Las funciones miembro solo pueden ser llamadas en asociación de un objeto, a diferencia de las
funciones definidas fuera de una clase.
Las funciones en el ejemplo anterior serían innecesarias si se declarara la variable “m_sIcon”
como publica pero esto iría en contra de la ocultación de la información que es uno de los
principios fundamentales de la programación orientada a objetos.
Al definir la clase utilizando miembros privados y públicos, se puede decir que un objeto tiene un
estado interno (miembros privados) y operaciones externas (miembros públicos).
objeto_icon1.Apariencia(":O");
objeto_icon2.Apariencia(":]");
Cada objeto llama la función “Apariencia()” para cambiar sus respectivas variables “m_sIcon”.
objeto_icon1.Muestra();
objeto_icon2.Muestra();
Los objetos despliegan el valor de la variable privada “m_sIcon” mediante sus funciones miembro
“Muestra()”.
objeto_icon1.Apariencia(":)");
objeto_icon1.Muestra();
objeto_icon2.Muestra();
Se llama otra vez la función “Apariencia()” asociada al “objeto_icono1” y en las se vuelven a
desplegar el contenido de las variables de cada objeto.
Ejercicio
Cree una clase Persona que contenga el nombre, dirección, teléfono y una función para
actualizar y otra para desplegar los datos.
4.7 Puntero this
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 137
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 143/212
Cada vez que se crea una instancia de una clase, el objeto ocupa espacio en memoria y “this” es
la palabra reservada con el valor de la dirección en memoria del objeto que está siendo
ejecutado.
En un objeto, “this” es un puntero a si mismo, éste es utilizado implícitamente para referenciar
todos los miembros del objeto; también puede ser utilizado en forma explicita.
El siguiente ejemplo es una modificación a la clase “CFecha” e incluye una función miembro que
recibe una referencia a un objeto del mismo tipo y comprueba si los datos que contienen los
objetos son iguales o diferentes, además comprueba sí trata de si mismo.
Listado
// cfechacompara.h
#pragma once
class CFecha {
private:
int mm, dd, aa;
public:
CFecha(int a_dd, int a_mm, int a_aa) {
mm = a_mm;
dd = a_dd;
aa = a_aa;
}void Fecha();
void Compara(CFecha &fecha);
};
void Compara(CFecha &fecha);
Esta función recibe una referencia a la clase “CFecha” (a sí misma).
Listado
// cfechacompara.cpp
#include "cfechacompara.h"
#include <iostream>
using namespace std;
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 138
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 144/212
void CFecha::Fecha() {
cout << dd << '/' << mm << '/'<< aa;
}
void CFecha::Compara(CFecha &fecha) {
if (&fecha == this) {
cout << "Fechas iguales, mismo objeto";
return;
}
// if (fecha.mm == this.mm
// && fecha.dd == this.dd & fecha.aa == this.aa)
if (fecha.mm == mm && fecha.dd == dd & fecha.aa == aa)
cout << "Fechas iguales";
else
cout << "Fechas diferentes";
}
if (&fecha == this) {
cout << "Fechas iguales, mismo objeto";
return;
}
Se compara la dirección en memoria de la referencia al objeto recibido con la dirección actual del
objeto que recibió la referencia, usando el “this”.
//if (fecha.mm == this.mm
// && fecha.dd == this.dd & fecha.aa == this.aa)
Las líneas que aparecen como comentario son idéntica en funcionalidad a las siguientes líneas:
if (fecha.mm == mm && fecha.dd == dd & fecha.aa ==
aa)
cout << "Fechas iguales";
elsecout << "Fechas diferentes";
Listado
// testcfechacompara.cpp
#include <iostream>
#include "cfechacompara.h"
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 139
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 145/212
using namespace std;
int main() {
CFecha f1(10, 1, 05);
CFecha f2(22, 1, 05);
f1.Fecha();
cout << "\t\t";
f1.Compara(f1);
cout << endl;
f2.Fecha();
cout << "\t\t";
f2.Compara(f1);
return 0;
}
Salida
10/1/5 Fechas iguales, mismo objeto
22/1/5 Fechas diferentes
CFecha f1(10, 1, 05);
CFecha f2(22, 1, 05);
Se declaran dos objetos de tipo “CFecha” y se inicializan mediante su constructor.
f1.Compara(f1);
El objeto “f1” manda llamar la función “Compara()” y le manda la dirección de sí mismo.
f2.Compara(f1);
El objeto “f2” manda llamar la función “Compara()” y le manda la dirección del objeto “f1”.
Ejercicios
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 140
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 146/212
3. Agregue funciones miembro a la clase “CFecha” en cfecha.h y cfecha.cpp para que actualice
el año, el mes y el día independientemente, así como funciones para que regrese solo el
año, mes y día respectivamente.
4. Hacer un programa con una clase hora que implemente una funcionalidad parecida a la de la
clase de fecha.
4.8 Constructores y destructoresConstructores
Los constructores son utilizados para inicializar variables miembro porque estas no se pueden
inicializar en el momento en que son declaradas.
Un constructor es una función miembro con el mismo nombre que la clase y no debe regresar un
valor; solo es usada para inicializar los datos del objeto. Las funciones constructor son llamadas
automáticamente cuando se crea un objeto (Una variable del tipo de la clase) sin necesidad de
hacer referencias a éstas.
Por ejemplo si el objeto tiene variables que se deben inicializar a cero o separar memoria
dinámicamente, estas operaciones se incluyen dentro del constructor.
El siguiente programa es una modificación del ejemplo anterior y muestra el uso de un
constructor y presenta como implementar las funciones miembro fuera de la interfase de la clase.
Listado
// emoticon2.cpp
#include <iostream>
#include <string>
using namespace std;
class CEmoticon {
private:
string m_sIcon;
public:
CEmoticon() { Apariencia(":|"); }
void Muestra(void){
cout << endl << m_sIcon;
}
void Apariencia(string a_sIcon);
};
void CEmoticon::Apariencia(string a_sIcon) {
m_sIcon = a_sIcon;
}
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 141
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 147/212
int main(){
CEmoticon objeto_icon1; // Declara un objeto de tipo CEmoticon
CEmoticon objeto_icon2;
objeto_icon1.Muestra();
objeto_icon2.Muestra();
cout << endl;
objeto_icon1.Apariencia(":D");
objeto_icon1.Muestra();
objeto_icon2.Muestra();
return 0;
}
Salida
:|
:|
:D
:|
CEmoticon() { Apariencia(":|"); }
La función “CEmoticon()” tiene el mismo nombre de la clase, por lo tanto es una función
constructor y esta es llamada automáticamente cuando se crean instancias de la clase.
Nótese que en el cuerpo de la función constructor se llama la función miembro “Apariencia()”,
aquí no se necesita el nombre del objeto, porque automáticamente se usa el objeto que se este
ejecutando (ver el operador “this”, al final de este capitulo)
En vez de llamar el método “Apariencia()” la función miembro anterior se pudo haber escrito
como:
CEmoticon() { m_sIcon = ":|"; }
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 142
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 148/212
void Apariencia(string a_sIcon);
A diferencia de la función miembro “Muestra()” la cual esta completamente implementada dentro
de la clase (En forma “inline”, ver capitulo de subprogramas), aquí solo se incluye el encabezado
de la función (El prototipo, ver capitulo de subprogramas) para indicar que pertenece a la clase, y
la implementación de la misma se realiza fuera de la declaración de la clase. El análisis de esta
manera de crear las clases se discute en el siguiente tema en este capitulo: “Clases y módulos”.
void CEmoticon::Apariencia(string a_sIcon) {
m_sIcon = a_sIcon;
}
Usando el nombre de la clase “CEmoticon” y el operador de alcance “::” se implementa la función
“Apariencia()” fuera de la declaración de la clase.
CEmoticon objeto_icon1; // Declara un objeto de tipo
CEmoticon
CEmoticon objeto_icon2;
Al declarar los objetos “objeto_icon1” y “objeto_icon2” se llama automáticamente la función
constructor “CEmoticon()”.
objeto_icon1.Muestra();
objeto_icon2.Muestra();
Muestra el contenido de cada objeto, a diferencia del ejemplo anterior esto se hace sin antes
llamar la función “Apariencia()” gracias a que el constructor ha inicializado la variable miembro
“m_sIcon” al crear los objetos.
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 143
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 149/212
Ejercicio
Discuta cuales son las ventajas y desventajas de usar constructores como inicializadores de las
variables miembro.
Clases y módulos
Al diseñar una clase es conveniente separar la interfase de la implementación, “la interfase dice
aquí está como es el objeto y estos son los métodos del objeto, la implementación muestra cómo
los métodos trabajan” [Eckel 1993]
La declaración de la clase es la interfase en C++, que a excepción de las funciones
implementadas dentro de la clase, solo indica cómo es el objeto. La práctica en C++ es escribir
la declaración de la clase en un archivo de encabezado y la implementación en un archivo con
extensión cpp.
La siguiente aplicación muestra una clase con una función constructor con argumentos y cómo
mandarle los argumentos al constructor al crear el objeto; también sigue la práctica común en C+
+ de crear un archivo de encabezado con la especificación de la clase y un archivo de código
(.cpp) con la implementación de la clase.
Listado
// cfecha.h
// clase implementada con módulos
// un constructor con argumentos
#pragma once
class CFecha {
private:
int mm, dd, aa;
public:
CFecha(int a_dd, int a_mm, int a_aa) {
mm = a_mm;
dd = a_dd;
aa = a_aa;
}
void Fecha();
void FechaCompleta();
};
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 144
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 150/212
CFecha(int a_dd, int a_mm, int a_aa) {
Se implementa el constructor con argumentos.
Listado
// cfecha.cpp// Implementacion de la clase cfecha
#include "cfecha.h"
#include <iostream>
using namespace std;
void CFecha::Fecha() {
cout << dd << '/' << mm << '/'<< aa;
}
void CFecha::FechaCompleta() {
char *meses[] = {
"Enero", "febrero", "Marzo", "Abril",
"Mayo", "Junio", "Julio", "Agosto",
"Septiembre", "Octubre", "Noviembre", "Diciembre"
};
cout << dd << " de " << meses[mm-1] << " del " << (2000 + aa);}
En este archivo se implementan dos de las funciones miembro de la clase definida en el archivo
de encabezado, esto permite incluir la clase en varias aplicaciones ya que la función “main()” no
está en este archivo.
char *meses[] = {
"Enero", "febrero", "Marzo", "Abril",
"Mayo", "Junio", "Julio", "Agosto",
"Septiembre", "Octubre", "Noviembre", "Diciembre"
};
Declara un arreglo de cadenas de caracteres y se inicializa con los nombres de los meses del
año.
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 145
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 151/212
cout << dd << " de " << meses[mm-1] << " del " << (2000 +
aa);
Despliega la fecha completa usando las variables con el numero de día, el numero de mes como
índice del arreglo de nombres de los meses (menos uno ya que los arreglos en C++ empiezan
en cero) y el numero de año mas el milenio “meses[mm-1] “ (claro que esta clase solo es útil sise utiliza en este milenio, pero espero que para entonces salga una edición nueva de este libro
con los ajustes necesario )
Listado
// testcfecha.cpp
#include <iostream>
#include "cfecha.h"
using namespace std;
int main() {
CFecha f1(10, 1, 9);
CFecha f2(15, 1, 10);
f1.Fecha();
cout << "\t\t";
f1.FechaCompleta();
cout << endl;
f2.Fecha();
cout << "\t\t";
f2.FechaCompleta();
return 0;
}
Salida
10/1/9 10 de Enero del 2009
15/1/10 15 de Enero del 2010
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 146
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 152/212
CFecha f1(10, 1, 05);
Se declara el objeto “f1”, ya que el constructor tiene argumentos se le tiene que mandar los
datos necesarios al declararlo, si el constructor no tuviera argumentos la declaración seria solo
“CFecha f1”.
Destructores
Un destructor es una función miembro con el mismo nombre que la clase, pero precedido por un
carácter tilde “~”. Una clase sólo tiene una función destructor, no tiene argumentos y no devuelve
ningún valor. Al igual que las demás funciones miembro puede estar definido dentro o fuera de la
clase.
El destructor es usado para realizar las operaciones necesarias para el objeto cuando este deja
de existir, como por ejemplo liberar espacio adquirido durante el tiempo de vida del objeto.
El siguiente programa es una modificación del ejemplo emoticon2.cpp presentado en el listado
7.2. Se usa un destructor y se muestra el orden de llamado del constructor y el destructor.
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 147
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 153/212
Listado
// emoticon_con.cpp
// uso de constructores y destructores
#include <iostream>
using namespace std;
class CEmoticon {
private:
string m_sIcon;
public:
CEmoticon(string a_sIcon);
~CEmoticon() {
cout << endl << "Adios mundo cruel! " << m_sIcon;
}
void Muestra(void){
cout << endl << "Yo estoy " << m_sIcon;
}
};
CEmoticon::CEmoticon(string a_sIcon) {
m_sIcon = a_sIcon;
cout << endl << "Acabo de nacer! " << m_sIcon;
}
int main(){
CEmoticon emoticon1(":)");
{
CEmoticon emoticon2(":(");
emoticon2.Muestra();
}
emoticon1.Muestra();
return 0;
}
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 148
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 154/212
Salida
Acabo de nacer! :)
Acabo de nacer! :(
Yo estoy :(
Adios mundo cruel! :( Yo estoy :)
Adios mundo cruel! :)
~CEmoticon() {
cout << ende << "Adios mundo cruel! " << m_sIcon;
}
Aquí se implementa el destructor el cual solo despliega un mensaje para anunciar que ha sido
llamado, igual que el constructor.
main(){
CEmoticon emoticon1(":)");
{
CEmoticon emoticon2(":|");
emoticon2.Muestra();
}
emoticon1.Muestra()
}
En la función principal se crean dos objetos, uno en el bloque de código de la función “main()
CEmoticon emoticon1(":)")” ; y el otro dentro de un bloque de código para mostrar la creación y
destrucción de los objetos como se observa en la salida del programa.
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 149
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 155/212
Miembros estáticos
Al crearse un objeto, se separa espacio para las variables por cada objeto creado, a excepción
de las variables miembro estáticas; éstas pertenecen a todos los objetos derivados de la clase.
Las variables estáticas son globales para todos los objetos de la misma clase; éstas variables
también son llamadas variables de la clase ya que su contenido no depende de cada objeto.Una clase puede contener datos y funciones estáticas.
Los siguientes tres listados de código presentan una aplicación donde dentro de un ciclo se
crean aleatoriamente varios objetos dentro de un arreglo de punteros, se muestran los objetos
creados y después se destruyen; todo esto llevando un conteo de los objetos creados y
destruidos en una variable miembro de tipo “static”.
Listado
// static_emoticon.h
// miembros estaticos
// definición clase CEmoticon
#pragma once
#include <string>
using namespace std;
class CEmoticon {
private:
static int m_iPoblacion;
string m_sIcon;
public:
CEmoticon(string a_sIcon);
~CEmoticon();
static int Poblacion() { return m_iPoblacion; }
void Muestra();
};
static int m_iPoblacion;Se declara una variable miembro de tipo “static”.
Listado
// static_emoticon.cpp
// implementacion de CEmoticon con miembros estaticos
#include <iostream>
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 150
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 156/212
#include "static_emoticon.h"
int CEmoticon::m_iPoblacion = 0;
CEmoticon::CEmoticon(string a_sIcon) {
m_iPoblacion++;
m_sIcon = a_sIcon;
}
CEmoticon::~CEmoticon() {
m_iPoblacion--;
}
void CEmoticon::Muestra() {
cout << " " << m_sIcon;
}
int CEmoticon::m_iPoblacion = 0;
Como la variable tipo “static” pertenece a la clase y no a un objeto en particular se inicializa
haciendo referencia a la clase.
m_iPoblacion++;
La variable se incrementa dentro del constructor; como el constructor se llama cada vez que secrea un objeto, se lleva un conteo de los objetos en esta variable.
m_iPoblacion--;
La variable se decrementa cada vez que un objeto ejecuta al destructor el cual se llama
automáticamente cada vez que el objeto se destruye.
Listado
// test_static_emoticon.cpp
// prueba la clase CEmoticon incluida en static_emoticon.cpp
#include <iostream>
#include <string>
#include <cstdio>
#include <ctime>
#include "static_emoticon.h"
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 151
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 157/212
int main(){
int nc, i;
CEmoticon *emoticon[10];
string op;
nc = 0;
srand((unsigned)time( NULL ));
do {
nc = rand() % 10;
for (i = 0; i < nc; i++)
emoticon[i] = new CEmoticon(":)");
cout << "Poblacion: " << CEmoticon::Poblacion()
<< endl;
for (i = 0; i < nc; i++)
emoticon[i]->Muestra();
for (i = 0; i < nc; i++)
delete emoticon[i];
cout << endl << "Continuar (s/n) ?";
cin >> op;
} while (op != "n" && op != "N");
return 0;
}
Salida
Poblacion: 2
:) :)
Continuar (s/n) ?sPoblacion: 9
:) :) :) :) :) :) :) :) :)
Continuar (s/n) ?s
Poblacion: 6
:) :) :) :) :) :)
Continuar (s/n) ?n
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 152
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 158/212
CEmoticon *emoticon[10];
Se declara un arreglo de punteros de tipo “CEmoticon”, note que aquí no se crean los objetos,
solo el espacio para almacenar diez direcciones a diez objetos del tipo “CEmoticon”.
nc = rand() % 10;
Dentro del ciclo se genera un número aleatorio entre el cero y nueve, para crear esta cantidad de
objetos y guardar sus direcciones en el arreglo de punteros.
for (i = 0; i < nc; i++)
emoticon[i] = new CEmoticon(":)");
Se crean los objetos dentro de un ciclo “for: controlado por el numero generado aleatoriamente.
cout << "Poblacion: " << CEmoticon::Poblacion() << "\n";
Una vez que se han creado los objetos se despliega la variable estática llamando la función
miembro “Población()”.
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 153
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 159/212
for (i = 0; i < nc; i++)
emoticon[i]->Muestra();
Despliegan los strings que contienen los objetos recién creados.
for (i = 0; i < nc; i++)
delete emoticon[i];
Los objetos se destruyen.
Las siguientes líneas controlan si se desea continuar dentro del ciclo principal; de ser así, todos
los objetos habrán sido destruidos y se volverá a empezar en cero objetos creados.
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 154
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 160/212
Capitulo 5
Herencia
5.1 Importancia de la herencia en la POOLa herencia es una manera de reutilizar código al crear clases nuevas en base a otras que ya
existen, esto ahorra tiempo de desarrollo al utilizar código probado anteriormente. Utilizando la
herencia el desarrollador puede decidir que partes de la clase reutiliza y cuales implementa
nuevamente para que se ajusten a las necesidades de la nueva clase.
Hay que notar que no todos los miembros de la clase pueden ser heredados, los constructores,
el destructor, los operadores de asignación y los miembros estáticos no son heredables.
5.2 Jerarquía de herenciaAl usar la herencia se forma con las clases derivadas estructuras jerárquicas en forma de árbol.
A la clase que va ser heredada se le llama clase base, superclase o clase padre y a la clase que
hereda se le llama clase derivada, subclase o clase hijo.
Mediante el uso de la jerarquía se implementa una relación de especialización/generalización
entre clases.
5.2.1 Conceptos de herencia simple y múltipleHerencia simple
La herencia simple significa que una clase es derivada de una sola clase a la vez.
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 156
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 161/212
Por ejemplo si se quiere realizar un programa para dibujar figuras, se puede empezar por el
elemento principal que todo dibujo contiene, un punto, de ahí una línea, un rectángulo, etc., y se
va reutilizando el código ya escrito de la clase anterior.
Ejemplo:
Donde:
1. La clase línea hereda de clase punto
2. La clase rectángulo hereda de clase línea (y a la vez de punto a través de
línea)
Herencia múltiple
La herencia múltiple es cuando una clase se deriva de más de una a la vez y hereda lascaracterísticas de todas las clases de donde se deriva.
Ejemplo:
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 157
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 162/212
Donde:
1. La clase CTiempo hereda de la clase CFecha y de clase CHora
5.2.2 Principios generales de diseño de jerarquíasLa jerarquía se debe empezar desde lo más genérico hasta lo más específico. Cada nivel de la
jerarquía debe reutilizar código del nivel anterior y extender la clase o clases de las cuales
heredo.
Ejemplo:
Solo los elementos de la clase que sean absolutamente necesarios para la comunicación
externa de los objetos deben de ser de tipo “puiblic”.
Los miembros que solo sean necesarios para las clases derivadas deben marcarse como
“protected”.
Todos los demás miembros de la clase deben ser de tipo “private”, esto es para encapsular el
objeto y reducir al mínimo los conflictos de acceso a los mismos, así como para aumentar la
flexibilidad del mantenimiento de la clase, al no estar expuestos es mas fácil cambiarlos, ya sea
de tipo de datos, nombres, etc.
Lo recomendable es hacer o seguir un análisis y diseño orientado a objetos antes de empezar a
codificar.
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 158
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 163/212
5.2.3 Especificadores de acceso a jerarquía de clasesAl crear una clase se cuenta con un control de acceso a los miembros de la misma que son
“private”, “protected” y “public”, este control se puede restringir aún mas al derivar.
Dependiendo del tipo de acceso con que cuenten los miembros de la clase base estos son
cambiados de acuerdo al modificador de acceso impuesto al derivarse.
Si al heredar se usa el
modificador de acceso:
Los miembros de la clase
base que sean:
Su acceso en la clase derivada
es:private private
protected
public
Inaccesible
private
privateprotected private
protected
public
Inaccesible
protected
protected
public private
protected
public
Inaccesible
protected
public
5.3 Definición de una clase baseCualquier clase puede ser una base clase, inclusive una clase derivada puede servir como clase
base para subsecuentes derivaciones.
La sintaxis para definir clases bases es igual a definir clases ordinarias, solo que ahora se debe
declarar como “protected” los miembros que se quiere que sean heredados por las clases
derivadas.
Tomar en cuenta la tabla anterior para asegurarse que las clases derivadas cuenten con el
acceso debido a los miembros de la clase base.
Se puede crear una clase con el solo propósito de ser heredada, a este tipo de clases se les
llama clases abstractas.
Listado
// cbase.h
// ejemplo de tipos de acceso para usar en la herencia
#pragma once
#include <string>
using namespace std;
class CBase {
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 159
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 164/212
private:
string strPrivado;
protected:
string strProtegido;
public:
string strPublico;
CBase(){
strPrivado = "Privado, dominio de esta clase";
strProtegido = "Protegido, dominio de la familia";
strPublico = "Publico, dominio publico";
}
};
Esta clase contiene los tres tipos de acceso y servirá como base para ser heredada mas
adelante, así como para mostrar el tipo de acceso de los miembros al usarla.
Listado
// testcbase.cpp
#include "cbase.h"
#include <iostream>
using namespace std;
int main(){
CBase base;
//cout << base.strPrivado << endl; // no accesible
//cout << base.strProtegido << endl; // no accesible
cout << base.strPublico << endl; // accesible porque es publico
return 0;
}
Salida
Publico, dominio publico
Note que el campo miembro de tipo “protected” actúa como tipo “private” para la clase base.
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 160
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 165/212
Listado
// CJugadorVirtual.h
// clase base, para ser heredada por otra
// los objetos generan un numero aleatorio entre
// 0 y 9
#pragma once
#include <iostream>
#include <cstdlib> // rand()
#include <ctime>
using namespace std;
class CJugadorVirtual {
protected:
int numero;
public:
CJugadorVirtual() {
numero = 0;
}
void Adivina() {
numero = rand() % 10;
}
int MiNumero() {
return numero;
}
};
protected:
int numero;
Aquí se declara un entero con control de acceso protegido, cada objeto debe generar un numero
aleatorio al llamar el método “Adivina()” y regresar el numero con el método “MiNumero()”, la
idea es que sea parte de un “jugador artificial” dentro de un programa y a la vez servir como
base para una clase que represente a un “jugador humano”.
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 161
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 166/212
Listado
// test_jugadorvirtual.cpp
// se genera un numero aleatorio en la funcion main
// y los objetos CJugadorVirtual "juegan" a
// "adivinar" el numero generado en main
#include <iostream>
#include <cstdlib> // srand()
#include <ctime> // time()
#include "CJugadorVirtual.h"
using namespace std;
int main() {
bool adivinado = false;
int numeroGenerado;
CJugadorVirtual j1;
CJugadorVirtual j2;
srand((unsigned)time( NULL ));
numeroGenerado = rand() % 10;
cout << "Estoy pensando en un numero entre 0 y 9..." << endl;
while (true) {
j1.Adivina();
j2.Adivina();
cout << endl << "Jugador uno dice " << j1.MiNumero();
cout << endl << "Jugador dos dice " << j2.MiNumero();
if (j1.MiNumero() == numeroGenerado)
adivinado = true;
if (j2.MiNumero() == numeroGenerado)
adivinado = true;
if (adivinado){
cout << endl << "Numero Adivinado!, el numero era "
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 162
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 167/212
<< numeroGenerado;
break;
}
else
cout << endl
<< "Los jugadores deben de intentar otra vez.\n";
}
return 0;
}
Salida
Estoy pensando en un numero entre 0 y 9...
Jugador uno dice 9 Jugador dos dice 9
Los jugadores deben de intentar otra vez.
Jugador uno dice 1
Jugador dos dice 4
Numero Adivinado!, el numero era 1
El programa genera un número aleatorio y usa la clase “CJugadorVirtual” para crear objetos quegeneren números y compararlos con el número generado dentro de “main”, esto para crear un
juego de “adivina el número que pienso”, en este caso no hay intervención externa y los
programas juegan “solos”.
Ejercicios
3.Modifique la siguiente clase para ser usada como clase base, siguiendo los principios de
diseño de la programación orientada a objetos, tip: es una sola línea la que hay que modificar.
// cpersona.h
// Ejercicio modificar para ser clase base
#pragma once
#include <iostream>
#include <string>
using namespace std;
class CPersona {
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 163
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 168/212
private:
string Nombre;
string Direccion;
string Telefono;
public:
void Captura(void);
void Despliega(void);
};
void CPersona::Captura(void) {
cout << endl << "Nombre : ";
getline(cin, Nombre, '\n');
cout << "Direccion: ";
getline(cin, Direccion, '\n');
cout << "Telefono : ";
getline(cin, Telefono, '\n');
}
void CPersona::Despliega(void) {
cout << endl << Nombre;
cout << endl << Direccion;
cout << endl << Telefono;
}
2. Realice un programa principal para que pruebe la clase “CPersona”
5.4 Definición de una clase derivadaUna clase derivada hereda la capacidad para llamar a funciones miembro de la clase base en los
objetos de la clase derivada.
Forma general:
class clase_derivada : modificador_de_acceso clase_base { … };
5.4.1 Constructores y destructores de clases derivadasSi la clase derivada no cuente con constructores, utiliza los de la clase base, en igual forma con
el destructor. En caso de que cuente con constructor o destructor debe estar coordinado con el
constructor y destructor de la clase base. El constructor de la clase derivada debe llamar al
constructor de la clase base y enviar los valores requeridos por el constructor de la clase base.
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 164
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 169/212
Si la clase base y la clase derivada cuentan con un constructor primero de ejecuta el constructor
de la clase base y después el de la clase derivada.
El orden de llamado de inicialización de las clases en la jerarquía de herencia es primero las
clases base de una clase derivada.
En el caso del destructor el orden de ejecución es inverso, primero la clase derivada y después
las clases base.
5.4.2 Conversión implícita de objetos de clase derivada a
objeto de clase baseUn 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.
Adicionalmente, un puntero a cualquier objeto será implícitamente convertido en un puntero del
tipo void * (Para asignar este a un puntero a otro tipo hace falta el uso de cast explícito.)
Listado
// hereda_cbase.cpp
// ejemplo de tipos de acceso herencia
#include <iostream>
#include <string>
#include "cbase.h"
using namespace std;
// Derivando en forma privada
class CDerivadaPrivada : private CBase {
public:
void Despliega() {
// no accesible, privado solo lo puede usar "CBase"
// cout << strPrivado << endl;
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 165
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 170/212
cout << strProtegido << endl;
cout << strPublico << endl;
}
};
// Derivando en forma protegida
class CDerivadaProtegida : protected CBase {
public:
void Despliega() {
// no accesible, privado solo lo puede usar "CBase"
// cout << strPrivado << endl;
cout << strProtegido << endl;
cout << strPublico << endl;
}
};
// Derivando en forma publica
class CDerivadaPublica : public CBase {
public:
void Despliega() {
//cout << strPrivado << endl;
cout << strProtegido << endl;
cout << strPublico << endl;
}
};
int main(){
CDerivadaPrivada privada;
privada.Despliega();
// no accesible al heredar se uso "private",
// y un publico se convierte en privado
// cout << privada.strPublico << endl;
CDerivadaProtegida protegida;
protegida.Despliega();
// no accesible al heredar se uso "protected",
// un publico se convierte en potegido
// cout << protegida.strPublico << endl;
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 166
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 171/212
CDerivadaPublica publica;
publica.Despliega();
// accesible al heredar se uso "public",
// un publico se queda como publico
cout << publica.strPublico << endl;
return 0;
}
Salida
Protegido, dominio de la familia
Publico, dominio publico
Protegido, dominio de la familiaPublico, dominio publico
Protegido, dominio de la familia
Publico, dominio publico
Publico, dominio publico
#include "cbase.h"
La clase CBase se incluye con aquí.
class CDerivadaPrivada : private CBase {
En esta línea se hereda en forma privada la clase “Cbase” y la clase “CDerivadaPrivada” obtiene
derecho a todos los miembros permitidos de la clase “CBase” como si fueran incluidos
directamente en la clase derivada.
class CDerivadaProtegida : protected CBase {
class CDerivadaPublica : public CBase {
En estas líneas se hereda de la clase “CBase” en forma protegida y publica respectivamente
obteniendo el acceso a los miembros de la clase “CBase” según las reglas de acceso y sepueden usar como de la misma manera que los miembros propios.
En la función principal “main()” se crean objetos de las tres clases derivadas de “CBase” y se
prueban sus miembros para mostrar el acceso que se obtiene con los diferentes controles de
acceso al heredar.
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 167
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 172/212
Listado
// CJugadorHumano.h
#pragma once
#include <iostream>
#include "CJugadorVirtual.h"
using namespace std;
class CJugadorHumano : public CJugadorVirtual {
public:
void Adivina() {
cout << " Numero que piensas? ";
cin >> numero;
}
};
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 168
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 173/212
class CJugadorHumano : public CJugadorVirtual {
En esta línea la clase “CJugadorHumano” hereda públicamente a la clase “CJugadorVirtual”
obteniendo el acceso a todos sus miembros permitidos.
protected:
int numero;
El campo numero es heredado y se vuelve de tipo “protected” para que pueda ser heredado en
clases derivadas si así se necesitara. El acceso esta garantizado para la clase
“CJugadorHumano” como si fuera escrito directamente en la clase.
CJugadorVirtual() {
int MiNumero() {
Estos métodos son heredados tal y como están, ya que la el constructor “CJugadorVirtual()” no
usa argumentos este se manda llamar automáticamente y no es necesario tomar medidas dentro
de la clase derivada.
void Adivina() {
En el caso de este método, se sobre-escribe ya que la implementación del método dentro de la
clase “CJugadorVirtual” no se aplica para esta clase y es necesario pedir el numero al usuario. Al
sobrescribir este método la clase derivada “desecha” el uso del método de la clase base, al
menos automáticamente, ya que aun puede ser llamado indicando el nombre de la clase base,
por ejemplo: “CBase::Adivina()” y ejecutaría le método de la clase padre en ve del método
propio.
Listado
// JuegoAdivina3.cpp
#include <iostream>
#include <ctime>
#include <cstdlib>
#include "CJugadorHumano.h"
using namespace std;
int main() {
bool adivinado = false;
int numeroGenerado;
CJugadorVirtual j1;
CJugadorVirtual j2;
CJugadorHumano jh;
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 169
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 174/212
srand((unsigned)time( NULL ));
numeroGenerado = rand() % 10;
cout << "Estoy pensando en un numero entre 0 y 9..." << endl;
while (true) {
j1.Adivina();
j2.Adivina();
jh.Adivina();
cout << endl << "Jugador uno dice " << j1.MiNumero();
cout << endl << "Jugador dos dice " << j2.MiNumero();
cout << endl << "Jugador tres dice " << jh.MiNumero();
if (j1.MiNumero() == numeroGenerado)
adivinado = true;
if (j2.MiNumero() == numeroGenerado)
adivinado = true;
if (jh.MiNumero() == numeroGenerado)
adivinado = true;
if (adivinado){
cout << endl << "Numero Adivinado!, el numero era "
<< numeroGenerado;
break;
}
else
cout << endl
<< "Los jugadores deben de intentar otra vez.\n";}
return 0;
}
Salida
Estoy pensando en un numero entre 0 y 9...
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 170
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 175/212
Numero que piensas? 3
Jugador uno dice 7
Jugador dos dice 6
Jugador tres dice 3Los jugadores deben de intentar otra vez.
Numero que piensas? 4
Jugador uno dice 1
Jugador dos dice 1
Jugador tres dice 4
Este ejemplo es casi idéntico al del programa “test_jugadorvirtual.cpp” con la diferencia que secrea un objeto de tipo “CJugadorHumano” y este objeto permite la participación externa al
preguntar por un número para comparar con el generado en el programa principal.
Ejercicios
4 Realicé una clase derivada de la clase “CPersona”, la cual se sugiere se llame “CEstudiante” que
además contenga los siguientes miembros:
string numero_control
int calificacion
Método Captura() – Debe de capturar tanto los campos heredados como los propios.Método Despliega() – Debe de desplegar en pantalla tanto los campos heredados como los
propios.
Método RegresaCalificacion() - regresar la calificación
2. Realice un programa principal para que pruebe la clase “CEstudiante”
5.5 Herencia múltipleForma general:
class clase_derivada : modificador_de_acceso clase_base,
modificador_de_acceso clase_base2, …
{
…
};
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 171
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 176/212
La siguiente clase es para usarla como una de las clases padres en el ejemplo de herencia
múltiple; es una modificación a la clase de “CFecha” mostrada en el capitulo de clases, la
modificación consiste en inicializar las variables que representan la fecha desde el sistema.
Listado
// autofecha.h
// clase CFecha, el constructor toma la fecha del sistema
#pragma once
#include <iostream>
#include <time>
using namespace std;
class CFecha {
protected:
int mm, dd, aa;
public:
CFecha(){
time_t ahora = time(NULL); // Hora y fecha de hoy
struct tm *tiempo = localtime(&ahora);
dd = tiempo->tm_mday;
mm = tiempo->tm_mon + 1;
aa = tiempo->tm_year - 100;
}
void Despliega() {
cout << dd << '/' << mm << '/'<< aa;
}
};
time_t ahora = time(NULL); // lee la fecha/hora del sistema
Se asigna el tiempo que regresa la función “time()”, al incluir el “NULL” como argumento esta
función regresa el tiempo actual del sistema.
struct tm *tiempo = localtime(&ahora);
“tm” es una estructura para almacenar información
correspondiente a varias funciones de manejo del tiempo.
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 172
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 177/212
La función “localtime()” acomoda la información del la
variable “ahora” para que se formatee el tiempo para ser
desplegado.
En las siguientes líneas se asignan las variables miembro de la estructura “tiempo” a las
variables miembro de la clase, que son “dd”, “mm” y “aa”.
La siguiente clase es para usarla como una de las clases padres en el ejemplo de herencia
múltiple, una clase para representar la hora la inicialización de las variables es desde el sistema.
Listado
// autohora.h
// clase CHora, el constructor toma la hora del sistema#pragma once
#include <iostream>
#include <time>
using namespace std;
class CHora {
protected:
int hh, mm, ss;
public:
CHora(){
time_t ahora = time(NULL); // Hora y fecha de hoy
struct tm *tiempo = localtime(&ahora);
hh = tiempo->tm_hour;
mm = tiempo->tm_min;
ss = tiempo->tm_sec;
}
void Despliega() {
cout << hh << ':' << mm << ':'<< ss;
}
};
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 173
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 178/212
La diferencia entre esta clase y la de “CFecha” es que se asignan las variables de la estructura
“tiempo” correspondientes a la hora a las variables miembro de la clase, que son “hh”, “mm” y
“ss”.
El siguiente ejemplo implementa la Clase “CTiempo” y esta hereda de dos clases “CFecha” y
“CHora”.
Listado
// tiempo.h
// Clase CTiempo, ejemplo de multiple herencia
#include "autofecha.h"
#include "autohora.h"
class CTiempo : public CFecha, public CHora {
public:
void Despliega(){
CFecha::Despliega();
cout << " ";
CHora::Despliega();
}
void CambiaFecha(int ad, int am, int aa) {
dd = ad;
CFecha::mm = am;
aa = aa;
}
void CambiaHora(int ah, int am, int as) {
hh = ah;
CHora::mm = am;
ss = as;
}
};
#include "autofecha.h"
#include "autohora.h"
Se incluyen los archivos de encabezado donde se encuentran las clases de “CFecha” y “CHora”.
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 174
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 179/212
class CTiempo : public CFecha, public CHora {
Se define la clase “CTiempo” y hereda de “CFecha” y de “CHora”, especificando el modificador
de acceso y separadas ambas por comas; ésta clase no tiene variables miembro por sí misma
solo utiliza las variables de las clases de las que se deriva.
void Despliega(){
CFecha::Despliega();
cout << " ";
CHora::Despliega();
}
En la implementación de la función “Despliega()” se imprime en pantalla la fecha y la hora, aquí
como ambas clases de las que hereda “CTiempo” cuentan con una función “Despliega()”, se
utiliza el operador de acceso “::” para especificar de cual clase se usa la función “Despliega()”.
void CambiaFecha(int ad, int am, int aa) {
dd = ad;
CFecha::mm = am;
aa = aa;
}
En este método se actualizan las variables. Nótese que las clases “CFecha” y “CHora” cuentan
con una variable que se llama igual por lo tanto es necesario utilizar el operador de acceso para
indicarle al compilador a cual clase pertenece la variable.
El siguiente programa hace uso de la clase creada en el programa anterior.
Listado
// testTiempo.cpp
// Prueba la clase con herencia multiple CTiempo
#include "tiempo.h"
int main(){
CFecha fecha;
fecha.Despliega();
cout << endl;
CHora hora;
hora.Despliega();
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 175
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 180/212
cout << endl;
CTiempo tiempo;
tiempo.Despliega();
tiempo.CambiaHora(12, 10, 20);
cout << endl;
tiempo.Despliega();
return 0;
}
Salida
19/6/9
16:50:6
19/6/9 16:50:6
19/6/9 12:10:20
La utilización de la clase “CTiempo” es idéntica a los demás ejemplos donde se declaran objetos,
independientemente de si fue una clase sola o sí uso herencia simple o herencia múltiple.
Ejercicio
1 Discuta las ventajas y desventajas del uso de la herencia
múltiple
2 Investigue que problemas se pueden presentar al usar
herencia múltiple
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 176
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 181/212
Capitulo 6
Polimorfismo
6.1 Concepto de polimorfismoEn C++ es la propiedad de ejecutar funciones miembro (métodos) de diferentes clases que
pertenecen a una jerarquía formada mediante la herencia, esto se obtiene usando funciones
virtuales y punteros a la clase base, este proceso se conoce como enlace dinámico.
También se puede implementar polimorfismo estático a través de la sobrecarga de funciones, lo
cual es la propiedad de tener más de una función miembro con el mismo nombre, donde cada
función puede pude implementar un proceso diferente (ver mas en el capitulo 2, subprogramas,
“2.7 Sobrecarga de subprogramas”)
El siguiente ejemplo muestra la sobrecarga de funciones, dos funciones constructor. Las
funciones se pueden sobrecargar independientemente de si son parte de una clase o no.
Listado
// cpolifecha.h
// clase implementada en módulos, dos constructores
#pragma once
class CFecha {
private:
int mm, dd, aa;
public:
CFecha();
CFecha(int a_dd, int a_mm, int a_aa) {
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 179
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 182/212
mm = a_mm;
dd = a_dd;
aa = a_aa;
}
void Fecha();
void FechaCompleta();
};
CFecha();
CFecha(int a_dd, int a_mm, int a_aa) {
Se declaran dos constructores con el mismo nombre pero uno sin argumentos y otro con tres
argumentos.
Listado// cpolifecha.cpp
#include "cpolifecha.h"
#include <iostream>
#include <ctime>
using namespace std;
CFecha::CFecha(){
time_t ahora = time(NULL); // Hora y fecha de hoy
struct tm *tiempo = localtime(&ahora);
dd = tiempo->tm_mday;
mm = tiempo->tm_mon + 1;
aa = tiempo->tm_year - 100;
}
void CFecha::Fecha() {
cout << dd << '/' << mm << '/'<< aa;
}
void CFecha::FechaCompleta() {
string meses[] = {"Enero", "febrero", "Marzo", "Abril",
"Mayo", "Junio", "Julio", "Agosto", "Septiembre",
"Octubre", "Noviembre", "Diciembre"};
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 180
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 183/212
cout << dd << " de " << meses[mm-1] << " del " << (2000 + aa);
}
Listado
// testcpolifecha.cpp
#include <iostream>
#include "cpolifecha.h"
using namespace std;
int main() {
CFecha f1(10, 1, 15);
CFecha f2;
f1.Fecha();
cout << "\t\t";
f1.FechaCompleta();
cout << endl;
f2.Fecha();
cout << "\t\t";
f2.FechaCompleta();
cout << endl;
return 0;
}
Salida
10/1/15 10 de Enero del 2015
1/6/9 1 de Junio del 2009
CFecha f1(10, 1, 05);
CFecha f2;
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 181
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 184/212
Se declaran dos objetos de tipo “CFecha”, el primer objeto recibe 3 argumentos, por lo tanto el
constructor con tres argumentos es llamado. En la siguiente línea al declarar el objeto “f2” se
llama el constructor sin argumentos.
Ejercicio
1 Discuta si es posible sobrecargar los métodos “Fecha()” y “FechaCompleta()”.
2 Discuta cual son las posibles ventajas y desventajas de la sobrecarga de funciones miembro.
6.2 Clase base abstractaUna clase base abstracta tiene funciones virtuales puras, es decir funciones que no son
implementadas en la clase; este tipo de clases es para ser usada como clase base solo para ser
derivada por otras clases y no para declarar instancias de la misma; al contener funciones
virtuales es imposible que se creen objetos del tipo de la clase (aunque sí se pueden crear
punteros que hagan referencia a este tipo de clases).
Si las clases derivadas no implementan las funciones virtuales puras, estas clases derivadas se
convierten también en clases abstractas. Si las clases derivadas implementan todas las
funciones virtuales puras se convierten en clases concretas y pueden ser usadas para instanciar
objetos.
Ejemplo:
virtual void dibujar() = 0;
El siguiente ejemplo implementa una clase abstracta y dos clases que se derivan de ella eimplementan las funciones virtuales puras definidas en la clase abstracta.
Listado
// abstracta.h
// ejemplo de clase con funciones virtuales puras
#pragma once
#include <iostream>
#include <string>
using namespace std;
class CPersona {
protected:
string m_sNombre;
public:
virtual void Agrega() = 0;
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 182
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 185/212
virtual void Muestra() = 0;
};
class CEmpleado : public CPersona {
protected:
float m_fSalario;
public:
void Agrega() {
cout << "Nombre ";
cin >> m_sNombre;
cout << "Salario ";
cin >> m_fSalario;
}
void Muestra() {
cout << "\nNombre " << m_sNombre;
cout << "\nSalario " << m_fSalario;
}
};
class CSocio : public CPersona {
protected:
int m_iAcciones;
public:
void Agrega() {
cout << "Nombre ";
cin >> m_sNombre;
cout << "Acciones ";
cin >> m_iAcciones;
}
void Muestra() {
cout << "\nNombre " << m_sNombre;
cout << "\nAcciones " << m_iAcciones;}
};
virtual void Agrega() = 0;
virtual void Muestra() = 0;
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 183
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 186/212
Aqui se declaran las funciones miembro como virtuales puras, esto le indica al compilador que
estas funciones van a ser implementadas por las clases derivadas.
Listado
// testAbstracta.cpp
// prueba la clae abstracta CPersona y sus clases derivadas
#include "abstracta.h"
int main(){
CPersona *persona;
CEmpleado empleado;
CSocio socio;
cout << "\nAgrega los datos del empleado " << endl;
empleado.Agrega();
cout << "\nAgrega los datos del socio " << endl;
socio.Agrega();
persona = &empleado;
persona->Muestra();
persona = &socio;
cout << endl;
persona->Muestra();
cout << endl;
return 0;
}
Salida
Agrega los datos del empleadoNombre Bruce
Salario 150
Agrega los datos del socio
Nombre Bjarne
Acciones 33
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 184
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 187/212
Nombre Bruce
Salario 150
Nombre BjarneAcciones 33
En este ejemplo se declaran dos objetos uno de tipo “CEmpleado” y otro de tipo “CSocio”, un
puntero a la clase base “CPersona”.
El objeto empleado y el objeto socio mandan llamar sus funciones miembro de “Agrega()” para
asignar valores a las variables miembro por medio de la entrada de datos del usuario, como se
muestra en los dos primeros párrafos de la salida.Mediante el puntero se accesa indirectamente a los objetos y se despliega el contenido las
variables miembro a través de la función “Muestra()”.
Ejercicio
5 Discuta si la clase abstracta en el ejemplo anterior podría no serlo y de ser así, porque.
6 Proponga situaciones donde sea útil usar una clase abstracta.
6.3 Subprogramas virtualesLas funciones virtuales son resueltas a la hora de ejecución del programa (run time), mediante
un mecanismo llamado ligamiento tardío (late-binding)
De esta manera un objeto se puede manipular como si fuera genérico accesando los objetos
derivados mediante el objeto base. Solo las funciones miembros pueden ser declaradas como
virtual.
Para declarar que una función de la clase base es virtual, a su prototipo se le antepone la
palabra reservada virtual, esta palabra solo debe ser usada en la declaración de la función, y no
en la definición de la función si se realiza fuera del cuerpo de la clase.
Ejemplo:
virtual void dibujar();
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 185
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 188/212
Para que el ligado tardío funcione, las funciones derivadas deben tener exactamente el mismo
nombre, incluyendo el numero de argumentos y sus tipos de datos, de no ser así el mecanismo
virtual es inoperable.
Listado
// virtual.h
// ejemplo de clase con funciones virtuales
#pragma once
#include <iostream>
#include <string>
using namespace std;
class CPersona {
protected:
string m_sNombre;
public:
virtual void Agrega() {
cout << "Nombre ";
cin >> m_sNombre;
}
virtual void Muestra() {
cout << "\nNombre " << m_sNombre;
}
};
class CEmpleado : public CPersona {
protected:
float m_fSalario;
public:
void Agrega() {
CPersona::Agrega();
cout << "Salario ";
cin >> m_fSalario;
}
void Muestra() {
CPersona::Muestra();
cout << "\nSalario " << m_fSalario;
}
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 186
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 189/212
};
class CSocio : public CPersona {
protected:
int m_iAcciones;
public:
void Agrega() {
CPersona::Agrega();
cout << "Acciones ";
cin >> m_iAcciones;
}
void Muestra() {
CPersona::Muestra();
cout << "\nAcciones " << m_iAcciones;
}
};
virtual void Agrega() {
Se declara (y empieza la implementación) de la función miembro “Agrega()” en forma virtual, esto
le indica al compilador que la resolución de esta función sea resuelta en tiempo de ejecución.
La clase “CPersona” a diferencia del ejemplo anterior no es
mas una clase abstracta ya que todas los métodos están
implementados.
Listado
// testVirtual.cpp
// prueba la clae abstracta CPersona y sus clases derivadas
#include "virtual.h"
int main(){
CPersona *persona;CPersona obj_persona;
CEmpleado empleado;
CSocio socio;
cout << "\nAgrega los datos de una persona " << endl;
obj_persona.Agrega();
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 187
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 190/212
cout << "\nAgrega los datos del empleado " << endl;
empleado.Agrega();
cout << "\nAgrega los datos del socio " << endl;
socio.Agrega();
// despliega los datos de obj_persona
obj_persona.Muestra();
// Despliega los datos de empleado y socio mediante
// el puntero persona
persona = &empleado;
persona->Muestra();
persona = &socio;
cout << endl;
persona->Muestra();
cout << endl;
return 0;
}
Salida
Agrega los datos de una persona
Nombre Batman
Agrega los datos del empleado
Nombre Superman
Salario 3500.50
Agrega los datos del socioNombre Tarzan
Acciones 33
Nombre Batman
Nombre Superman
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 188
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 191/212
Salario 3500.5
Nombre Tarzan
Acciones 33
CPersona obj_persona;
Aquí se declara un objeto de tipo “CPersona”, note que la clase “CPersona” del programa
“testAbstracta.cpp” no puede ser usada para instanciar objetos ya que es una clase abstracta
porque tiene funciones virtuales puras, no así en este ejemplo que las funciones virtuales están
plenamente implementadas.
Nota:
El uso de funciones miembro virtuales permite acceder a los métodos virtuales de las clasesderivadas usando indireccion mediante un puntero de tipo clase base.
Los métodos virtuales puros garantiza el acceso a los métodos de las clases derivadas
mediante la clase base aun cuando la clase base no cuente con suficientes datos para
implementar tales métodos.
6.4 Destructores virtualesLos destructores virtuales son como todas demás funciones miembro, por ejemplo, si en una
jerarquía de clases tiene destructores y se accesan los objetos de las clases derivadas mediante
un puntero a la clase base, al momento de que un objeto es destruido y si el destructor de la
clase base no es virtual, se llamara el destructor de la clase base y no a los demás destructores
de la jerarquía.
Cuando el destructor de la clase base es virtual y es llamado para destruir el objeto se llama a
todos los destructores que estén hacia arriba en la jerarquía de la herencia.
Como regla general, si en una clase existen funciones virtuales, el destructor debe ser virtual.
Listado
// destructor_virtual.cpp
#include <iostream>
using namespace std;
class CBase {
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 189
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 192/212
public:
// no virtual, posible problema
// ~CBase() {
virtual ~CBase() {
cout << " Destruyendo CBase" << endl;
}
virtual void Metodo() {
cout << "CBase::Metodo()" << endl;
}
};
class CDerivada1 : public CBase {
public:
~CDerivada1() {
cout << "Destruyendo CDerivada1" << endl;
}
void Metodo() {
cout << "CDerivada1::Metodo()" << endl;
}
};
class CDerivada2 : public CDerivada1 {
public:
~CDerivada2() {
cout << " Destruyendo CDerivada2" << endl;
}
void Metodo() {
cout << "CDerivada2::Metodo()" << endl;
}
};
main() {// puntero clase base a objeto derivado
CBase * pBase = new CDerivada2;
pBase->Metodo(); // llamada a función virtual
delete pBase; // borrar puntero a clase base
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 190
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 193/212
return 0;
}
Salida sin destructor virtual
CDerivada2::Metodo()Destruyendo CBase
Salida con destructor virtual
CDerivada2::Metodo()
Destruyendo CDerivada2
Destruyendo CDerivada1
Destruyendo CBase
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 191
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 194/212
Capitulo 7
Archivos
7.1 Clases de E/S Clase base abstractaStream es la clase base abstracta de E/S, esta es compatible con bytes de lectura y escritura.
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 de su
almacenamiento.
Corrientes de flujoEl sistema de E/S de C++ proporciona una interfaz independiente del dispositivo real al que se
accede; esto es una abstracción entre el programador y el dispositivo que se usa. Esta
abstracción se llama corriente y el dispositivo real se llama archivo.
Corrientes
Almacenamiento temporal de archivo para transformar los dispositivos físicos en un
almacenamiento lógico. Esto permite que las corrientes sean independientes de los dispositivos.
Existen dos tipos de corrientes: texto y binarias.
7.2 Realizar entrada y salida de textoArchivos de texto
Las corrientes de texto son una secuencia de caracteres organizadas en líneas terminadas por
un carácter nueva línea. La traducción del carácter nueva línea depende de la implementación.
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 193
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 195/212
Entrada de texto
La entrada o también llamada lectura es la transferencia de datos desde una secuencia a una
estructura de datos, como, por ejemplo, una matriz de bytes.
Salida de texto
La salida, también llamada escritura consiste en la transferencia de información desde un origen
de datos a una secuencia.
Operaciones de búsqueda
Las operaciones de búsqueda consisten en la consulta y modificación de la posición actual en
una secuencia.
7.3 Leer y escribir archivosEn el archivo fstream están definidas varias clases de entrada y salida, incluyendo ifstream –
flujo de entrada, ofstream – flujo de salida. Para leer y/o escribir en un archivo se crea un objeto
de tipo fstream.
Forma general:
fstream objeto(nombre_archivo, modo);
Donde modo es:
ios::in abre archivo existente para lecturaios::out abre archivo para escrituraios::out | ios::trunc crea archivo para escritura o trunca el archivo existenteios::out | ios::app abre archivo existente para agregarios::out | ios::in abre archivo existente para lectura y escrituraios::in | ios::out | ios::trunc trunca el archivo existente o crea archivo para lectura y
escrituraios::in | ios::out | ios::app abre el archivo existente o crea archivo para lectura y
escrituraios::binary para archivos binarios
Lectura de un archivo de texto
Se crea el objeto con fstream nombre_del_objeto, indicando que es de lectura con el
manipulador ios::in.
Ejemplo:
fstream entrada(“archivo.txt”, ios::in);
Listado
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 194
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 196/212
// muestra.cpp
// ejemplo de lectura de un archivo de texto
// muestra un archivo de texto en la salida estandard
#include <iostream>
#include <fstream>
#include <cstdlib>
using namespace std;
int main() {
char szArchivo[20];
char c;
cout << "Archivo a mostrar? ";
cin >> szArchivo;
fstream entrada(szArchivo, ios::in);
if (entrada.fail()) {
cout << "Error al abrir archivo! Abortando";
exit(1); // termina la ejecucion del programa
}
while (!entrada.eof()){
entrada.get(c);
cout << c;
}
entrada.close();
return 0;
}
Salida
Archivo a mostrar? primer.cpp// Primer.cpp
// Escribe un mensaje en pantalla
#include <iostream>
using namespace std;
int main()
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 195
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 197/212
{
cout << "Este es mi primer programa en C++";
return 0;
}
fstream entrada(szArchivo, ios::in);
Se crea el objeto de tipo “fstream”, y se intenta abrir el
archivo que indica la cadena de caracteres “szArchivo”; el
manipulador “ios::in” indica abrirlo en modo solo lectura.
La información sobre el éxito o fracaso se almacena en
“basic_ios:réstate”.
if (entrada.fail()) {
La función miembro “fail()”, regresa el numero uno o “true” o bien un cero o “false” dependiendo
de la información en “basic_ios::réstate”.
En caso de error de creación del objeto termina la ejecución del programa al llamar la función
“exit()”.
while (!entrada.eof()){“eof()”, regresa un cero o “false” si no se ha alcanzado el
final del archivo y uno o “trae” si esta en el fin de
archivo.
entrada.get(c);
“get()”, lee un carácter del flujo de entrada y lo asigna a
la variable “c”.
entrada.close();
“close()”, cierra el archivo.
Ejercicio
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 196
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 198/212
Escriba un programa que lea un archivo de texto y lo despliegue en mayúsculas en la salida
estándar.
Escritura en un archivo de texto
Para escribir en un archivo se crea un objeto de tipo “fstream”, con la sentencia “fstream
nombre_del_objeto”, indicando que es de escritura con el manipulador “ios::out”. Al crear el
objeto, si el archivo físico no existe se crea físicamente en blanco, si ya existe se sobrescribe en
blanco.
Ejemplo:
fstream salida(“archivo.txt”, ios::out);
El siguiente programa de ejemplo lee un archivo de texto y la va escribiendo en otro archivo de
texto pero en forma encriptada. La técnica usada para encriptar el archivo se basa en desfasar
en uno cada carácter.
Ejemplo:
Teniendo la cadena: “HOLA”
H O L A \0
El correspondiente código ascii para cada letra es:
72 48 76 64 \0
Si se le suma un uno a cada código:72 = H
72 + 1 = 73
73 = J
Toda la cadena en ascii con cada elemento incrementado en uno:
73 49 77 65 \0
Por lo tanto la cadena queda como: “J1MB”
J 1 M B \0
Para desencriptarla solo hay que restarle uno a cada elemento.
Listado
// encripta.cpp
// ejemplo de lectura y de escritura a archivos de texto.
// lee un archivo de entrada, desfasa el caracter leido y
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 197
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 199/212
// lo escribe en el archivo de salida
#include <iostream>
#include <fstream>
#include <cstdlib>
using namespace std;
int main() {
char szEntrada[20];
char szSalida[20];
char c;
cout << "Archivo a encriptar? ";
cin >> szEntrada;
cout << "Guardar archivo encriptado en? ";
cin >> szSalida;
fstream entrada(szEntrada, ios::in);
fstream salida(szSalida, ios::out);
if (entrada.fail()) {
cout << "Error al abrir archivo de entrada! Abortando";
exit(1);
}
if (salida.fail()) {
cout << "Error al abrir archivo de salida! Abortando";
exit(1);
}
while (!entrada.eof()){
entrada.get(c);
salida.put(c+1); // encripta
}
entrada.close();salida.close();
return 0;
}
Salida
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 198
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 200/212
Archivo a encriptar? primer.cpp
Guardar archivo encriptado en? primer.txt
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 199
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 201/212
Nota, Listado del archivo primer.txt:
00!Qsjnfs/dqq
00!Ftdsjcf!vo!nfotbkf!fo!qboubmmb$jodmvef!=jptusfbn?
vtjoh!obnftqbdf!tue<
jou!nbjo)*
|
!!!dpvu!==!#Ftuf!ft!nj!qsjnfs!qsphsbnb!fo!D,,#<
!!!sfuvso!1<
~
fstream entrada(szEntrada, ios::in);
fstream salida(szSalida, ios::out);
Se crean y se abren los archivos de entrada y de salida.
while (!entrada.eof()){
entrada.get(c);
salida.put(c+1); // encripta
}
Se recorre el archivo de entrada leyendo carácter por carácter y se escribe en la salida
sumándole un uno para encriptarlo.
entrada.close();
salida.close();
La llamada al método “close()” cierra el archivo.
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 200
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 202/212
Ejercicios
4.Escriba un programa que lea un archivo de texto y lo escriba en un nuevo archivo de texto –
copie el contenido de un archivo de texto existente en otro.
5.Desarrolle un programa que lea una cadena de caracteres y la grabe en un archivo de texto.
6.Modifique el programa encripta.cpp para que desencripte un archivo.
Lectura y Escritura en un archivo de texto
Para modificar un archivo (leer y escribir en un mismo archivo) se crea un objeto de tipo
“fstream”, con la sentencia “fstream nombre_del_objeto”, indicando que es de lectura y escritura
con los manipuladores “ios::in | ios::out | ios::app”.
Al crear el objeto, si el archivo físico no existe se crea físicamente en blanco, si ya existe lo abre
para lectura y escritura.
Ejemplo:
fstream archivo(“nombre_archivo.txt”, ios::in | ios::out | ios::app);
Para posicionarse en una parte del archivo se usa la función miembro “seekg”
Ejemplo:
// se posiciona exactamente al final del archivo
archivo.seekg(0, ios::end);
//se posiciona 10 caracteres despues del inicio
archivo.seekg(10, ios::beg);
El siguiente programa de ejemplo ilustra la entrada y salida en un solo archivo, implementando
una bitácora básica, la idea principal es ir agregando texto en un archivo existente, para llevar un
control de las actividades realizadas.
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 201
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 203/212
Listado
// bitacora.cpp
// abre un archivo para E/S y agrega texto al final del mismo
#include <iostream>
#include <fstream>#include <cstdlib>
using namespace std;
int main() {
char szTexto[256];
fstream esArchivo("bitacora.txt", ios::in | ios::out | ios::app);
if (esArchivo.fail()) {cout << "Error al abrir archivo! Abortando";
exit(1);
}
cout << "Texto? ";
cin.getline(szTexto, 255);
esArchivo.seekg(0, ios::end);
esArchivo << szTexto << "\n";
esArchivo.close();
return 0;
}
Salida
Texto? Punteros, referencias y arreglos
Nota, Listado del archivo bitacora.txt:
Fundamentos del lenguaje
subprogramas
Punteros, referencias y arreglos
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 202
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 204/212
fstream esArchivo("bitacora.txt", ios::in | ios::out |
ios::app);
Se crea el objeto “esArchivo”, y se abre de entrada y salida con “ios::in y ios::out”
respectivamente, se agrega el manipulador “ios::app”, para que en caso de que no exista el
archivo éste sea creado.
cin.getline(szTexto, 255);
“getline()”, lee toda una línea del flujo de entrada, con un
máximo de 255 caracteres
esArchivo.seekg(0, ios::end);
Al abrir un archivo para lectura, el indicador de lectura
del flujo de entrada se posiciona al inicio del archivo.
Como lo que se quiere es agregar texto al final del archivo
se usa el “seekg()”, para mover el indicador al final del
archivo. De no hacer esto, cualquier texto agregado al
archivo sobrescribe el existente.
esArchivo << szTexto << "\n";
Ya que “esArchivo” es un flujo de datos y “fstream” se
deriva de “basic_stream”, se asigna la cadena con el
operador “<<”, tal y como se hace con el objeto “cout”.
7.4 Realizar entrada y salida binariaArchivos binarios
Los archivos binarios son archivos no formateados; se utilizan para manejar los datos byte por
byte. Se usa el manipulador “ios::binary” al abrir el archivo y no se usan los operadores “<<”,
“>>”.
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 203
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 205/212
El siguiente ejemplo es la versión dos de la bitácora, usando estructuras para incluir el porciento
terminado de la tarea a grabar en la bitácora, además cuenta con un menú para con las
opciones de mostrar el contenido del archivo y agregar nuevos datos.
Listado
// bitacorax.cpp
// agrega texto al final de un archivo
#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>
using namespace std;
const int LON = 80;
struct BitacoraX {
int iPorcientoTerminado;
char szTexto[LON];
};
int main() {
BitacoraX bitacora;
int iOpcion, i;
fstream esArchivo("bitacorax.dat",
ios::out | ios::in | ios_base::app | ios::binary);
if (esArchivo.fail()) {
cout << "Error al abrir archivo! Abortando";
exit(1);
}
do {
cout << "\n1. Muestra";
cout << "\n2. Agrega";
cout << "\n3. Termina";
cout << "\nOpcion? ";
cin >> iOpcion;
cin.ignore();
switch (iOpcion) {
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 204
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 206/212
case 1:
cout << "Porciento\tTexto\n";
cout <<
"-------------------------------------------------------"
<< endl;
esArchivo.clear();
esArchivo.seekg(0, ios::beg);
esArchivo.read((char *)&bitacora,
sizeof(struct BitacoraX));
while (!esArchivo.eof()){
cout << bitacora.iPorcientoTerminado
<< "\t\t" << bitacora.szTexto << endl;
esArchivo.read((char *)&bitacora,
sizeof(BitacoraX));
}
break;
case 2:
cout << "\nTexto ? ";
cin.getline(bitacora.szTexto, LON-1);
cout << "Porciento terminado? ";
cin >> bitacora.iPorcientoTerminado;
esArchivo.clear();
esArchivo.seekg(0, ios::end);
esArchivo.write((const char *)&bitacora, sizeof(BitacoraX));
esArchivo.flush();
break;
case 3:
break;
default:
cout << "Opcion no implementada";
}
} while (iOpcion != 3);
esArchivo.close();
return 0;
}
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 205
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 207/212
Salida
1. Muestra
2. Agrega
3. Termina
Opcion? 1
Porciento Texto
-------------------------------------------------------------
100 Instrucciones basicas
100 control de flujo
70 arreglos
1. Muestra
2. Agrega
3. Termina
Opcion? 2
Texto ? Archivos y estructuras
Porciento terminado? 60
1. Muestra
2. Agrega
3. Termina
Opcion? 3
El programa incluye un ciclo donde se presenta un menú para
seleccionar si se quiere mostrar todos los elementos del
archivo, agregar un elemento o terminar el ciclo y por
consiguiente cerrar el archivo y terminar la ejecución delprograma.
La opción ingresada se compara en un “switch”, y en caso de
ser la opción 1, se ejecuta el “case 1:” y despliega unas
líneas de encabezado.
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 206
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 208/212
esArchivo.clear();
Al abrir el archivo, su indicador se encuentra en el inicio
del mismo pero al recorrerlo en modo de lectura una vez, se
prende la bandera de “eof” y se queda así. “clear()”, borra
la bandera puesta al alcanzar el fin de archivo -eof- para
recorrerlo desde el inicio tantas veces como el usuario así
lo desee.
esArchivo.seekg(0, ios::beg);
seekg(), posiciona el indicador de archivo al inicio, para
recorrerlo mientras no sea fin de archivo.
esArchivo.read((char *)&bitacora, sizeof(struct BitacoraX));
El método “read()”, recibe dos parámetros: el primero “(char
*)&bitácora” es el buffer donde se almacenan los datos
obtenidos del archivo y el segundo parámetro
“sizeof(BitacoraX)” indica el tamaño del buffer; en este
caso se invoca la función “sizeof()” la cual regresa el
tamaño en bytes del tipo de dato recibido como parámetro (en
este ejemplo la estructura “BitacoraX").
esArchivo.seekg(0, ios::end);
“seekg()”, posiciona el indicador de archivo al final, para
agregar datos.
esArchivo.write((const char *)&bitacora, sizeof(struct
BitacoraX));
El método “write()”, recibe dos parámetros: el primero
“(const char *)&bitácora” es el buffer donde están
almacenados los datos obtenidos que se van a grabar al
archivo y el segundo parámetro “sizeof(BitacoraX)” indica el
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 207
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 209/212
tamaño del buffer; en este caso se invoca la función
“sizeof()” la cual regresa el tamaño en bytes del tipo de
dato recibido como parámetro (en este ejemplo la estructura
“BitácoraX”).
esArchivo.flush();
“flush()”, este método graba el flujo del archivo al
dispositivo de almacenamiento físico, esto es para
actualizar el contenido del archivo.
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 208
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 210/212
Ejercicio
Realice un programa donde utilice archivos binarios, que
grabe y recupere la siguiente estructura:
struct SArticulo {
int clave;
char descripcion[40];
float precio;
};
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 209
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 211/212
Bibliografía
[Stroustrup 1997] Bjarne Stroustrup: “The C++ Programming Language” Third Edition Addison-
Wesley 1997
[Stroustrup 1993] Bjarne Stroustrup: “El lenguaje de programación C++” Segunda Edición
Addison-Wesley/Diaz de Santos 1993
[Hernandez 2002] Enrique Hernández Orallo, Jose Hernández Orallo y Ma. Carmen Juan
Lizandra: “C++ Estándar” Parainfo Thomson Learning 2002
[Eckel 1993] Bruce Eckel: “C++ Inside & Out” Osborne McGraw-Hill 1993
[Ellis 1994] Margaret A. Ellis y Bjarne Stroustrup: “C++ Manual de referencia con anotaciones”
Addison-Wesley/Diaz de Santos 1994
[Eckel 2000] Bruce Eckel: “Thinking in C++” 2nd ed. volume 1 http://www.BruceEckel.com 2000
[Deitel 1995] H.M. Deitel y P. J. Deitel: “Como programar en C/C++” segunda edición Pearson /
Prentice Hall 1995
[Visual C++ 2008 Express Edition] Microsoft Corporation: “Ayuda Visual C++ 2008 ExpressEdition” Microsoft Corporation
[Builder C++ 5.0] Borland, Inprise Corporation: “Ayuda C++ Builder 5.0” Borland, Inprise
Corporation
[Kernighan 1991] Brian W. Kernighan y Dennis M. Ritchie: “El lenguaje de programación C”
(c) copyright 2008-2012 Rogelio Cesar Rodriguez Cervantes 209
5/14/2018 Tutorial Profr. Rogelio Cesar - slidepdf.com
http://slidepdf.com/reader/full/tutorial-profr-rogelio-cesar 212/212
segunda edición Prentice Hall 1991
[Schildt 1990] Herlbert Schildt: “C The Complete Reference” second edition Osborne McGraw-
Hill 1990
[Rodriguez 2006] Rogelio Cesar Rodriguez Cervantes “Guía para el aprendizaje sistemático del
lenguaje de programación C++”, Proyecto utilitario para presentar examen profesional de
conocimientos para la Maestría en tecnología Informática en la Universidad Autónoma de
Tamaulipas, México.