CURSO de C++ Ignacio López Introducción al lenguaje C++ • Visión General • Objetivos del Curso C++ • Conceptos básicos de la programación orientada a objetos (OOP) Visión General I – Curso de C++ • • • • Introducción al lenguaje C++ Conceptos básicos de C++ Conceptos avanzados de C++ Librerías C++ – Integración Rational Rose y C++ – Mesa redonda Visión General II • Curso programación por eventos : Interfaz de Usuario • Curso Persistencia de objetos: Gestión de Archivos y Bases de datos • Curso Sistemas operativos: Windows 2000, Unix, Linux • Curso: Concurrencia y Sistemas distribuidos (Java, Internet) • Curso Reusabilidad y portabilidad: Creación de componentes (Bibliotecario): OCXs, DLLs, etc. Visión General III • Normalización de Herramientas SW y Sistemas operativos • Normalización de Documentación, Metodología y Calidad de SW Conceptos básicos de la programación orientada a objetos (OOP) • • • • • Abstracción Encapsulación Herencia Polimorfismo OOP y C++ Mejoras de C++ respecto a C (I) • Programa principal • Comentarios • Entrada y salida – Uso de Streams para entrada y salida – Formateo – Redireccionamiento de entrada/salida • • • • Posición en el programa para declarar variables El operador de ambito (scope) :: para uso de variables globales El cualificador Const El tipo enumeración Programa principal • • • • • • • • Función especial que es el punto de entrada de un programa No se puede invocar Si al final se quiere enviar un codigo de vuelta al proceso padre (sistema operativo) definirla la vuelta del tipo int y usar return: int main (int argcount, char * arg[ |) { … return o; } Si no se quiere enviar código de vuelta usar void y exit, si es necesario. void main (int argcount, char * arg[ |) { … exit; } No hay que definir prototipo de función Tipos de main: – Tipo Consola (MSDOS, UNIX): #include <stdio.h> void main (int argcount, char * arg[ |) { printf (" Hola mundo!\n"); } – Tipo Ventana (MS Windows, etc.) Comentarios • • Tipo C++: comienzo //, terminación: final de linea – // esto es un comentario Tipo C: Comienzo /*, terminacion */ – Puenen incluir varias lineas – No son anidables – Puede incluir varios comentarios tipo C++ – Ejemplos: • /* esto es un comentario en una linea */ • /* • esto es un comentario • en varias lineas • // con comentarios tipo C++ • */ Entrada/Salida • • • • • • • • • • Operador de salida << : argumento1s << argumento2. Escribe argumento2 en argumento1s. Operador de entrada >>: argumento1e >> argumento2. Lee argumento2 en argumento1e. operador1s: cout : dispositivo estandar de salida operador1s: cin : dispositivo estandar de entrada operador2: constante o variable de tipo estandad (char, int, float,…) Estos operadores y sus dispositivos están definidos en la directiva: #include <iostream.h> Ventajas No nesesitan formato (%s, %d,…), respecto a: printf ("%s%d%f\n" sNombre, iEdad, fAltura); scanf ("%s%d%f\n" sNombre, &iEdad, &fAltura); Ejemplo entrada /salida #include <iostream.h> void main () { char nombre[30|; int iEdad; float fAltura; cout << "Entrar nombre edad y altura (separador blanco)\n"; cin >> nombre >> iEdad >> fAltura; cout << nombre << iNum1 << fNum2 << "\n"; } Posición en el programa para declarar variables • En C: En el comienzo del módulo y/o comienzo de funciones • En C++: Casi en cualquier lugar; y antes de referenciarla Ej.: en el mismo instante del uso de la variable. – Ejemplos: • for (int i=0; i<100; i++) valido • if (int i == 0) inválido El operador :: de ámbito (scope) • En C: una variable local tiene precedencia a una global • En C++: lo anterior se puede cambiar anteponiendo :: a la variable global (no a una variable local de un anidamiento superior) • Ejemplo: int iCantidad =123; // variable global void main () { int iCantidad = 456; // variable local cout << :: iCantidad; // imprime la variable global cout << iCantidad; // imprime la variable local } El cualificador const • Convierte variables en constantes, es decir, especifica que la variable es de solo lectura, excepto cuando se inicializa. • Constante tipo C: #define PI 3.1416 • Constante C++: const int PI = 3.1416; • Constante de variable tipo predefinido: const float fValor = 5.2; • Constante puntero: const char *ptr = miBuffer; • Parámetro Constante en función: int f1 (cont int iX) • Constante en vuelta función: int f1 (int iX) const • Ventaja de const respecto a #define es que a ellas puede acceder con un debugger simbólico. El tipo enumeración (enum) • Define un tipo del usuario y declara un conjunto de constantes literales. • Definición del tipo color en c/C++: Enum Color {rojo, verde, azul}; • Uso del tipo color en C: enum Color cSombrero; // se usa enum • Uso del tipo color en C++: Color cSombrero; // no se usa enum • Los valores enteros por defecto asignados al tipo son: 0, 1, 2, … • Los valores enteros se pueden asignar e incluso repetir: • Ej.: enum Color (rojo =1, verde, azul =1); // da los valores 1, 2, 1 respectivamente. Mejoras de C++ respecto a C (II) Funciones • • • • • • • • • • • Prototipos de funciones Viejo estilo declaracion parámetros no permitido Declaración obligatoria de prototipos de funciones Argumentos de función por defecto Funciones inline Sobrecarga de funciones Asignación de memoria Operador new Operador delete Formas de pasar parámetros (valor, *referencia, &puntero) Especificaciones para el montador (combinar módulos C y C++) Prototipos de funciones (chequeo de tipos) • Un prototipo de función es su declaración -signatura-: valor de vuelta nombre (modificador tipo argumento variable,...) • Ej.: int suma (int a, int b); • No se permite la decharación al vieje estilo: int suma ( a, b) int a,b; { } • En la cabecera del módulo en el que se implementa o invoca a la función, obligatoriamente tiene que incluirse su declaración (.h) para que el compilador chequee los tipos. Argumentos por defecto en funciones • • • • Una función declarada como: void funcion1 (int i=5, double d = 1.23); Se puede invocar de todas estas maneras: funcion1 (13, 2.7); // reescribe los valores por defecto • funcion1 (4); // pasa 4, y el valor por defecto 1.23 • funcion1 (); // pasa valores defecto 5, 1.23 • funcion1 ( , 2.7) // error, no se pueden omitir los parámetros anteriores Funciones inline • • • • El cualificador inline colocado al comienzo de la declaración de una función, indica al compilador que coloque una copia de la función, en los lugares que esta se invoque. Se usa solo cuando las funciones son pequeñas o se llaman en pocos sitios. Son equivalentes a las macros, pero sin efectos laterales, ya que se realiza la comprobación de tipos. Ejemplo: – Declaración: inline int getEdad ( ); – Definición: inline int getEdad ( ) {return persona1.edad; } Invocación: iEdadPepe = getEdad(); Sobrecarga de funciones (operadores) • Sobrecarga significa un mismo nombre puede tener diversos significados. • La ambigüedad se resuelve por el contexto • Dos funciones que tienen el mismo nombre, pueden tener: – los mismos parámetros (número y tipo): Ej.: rectan.pintar (); circu.pintar (); – distintos parámetros (número y tipo): Ej.: xx.pintar (); yy.pintar (vv); – no pueden tener distinto valor de vuelta • Dos funciones que tienen el mismo nombre, pueden realizar: – la misma tarea (con iguales o distintos parámetros) – generalmente tareas distintas (con iguales o distintos parámetros). Operadores new y delete • • Es una alternativa a malloc para asignar (new) o desasignar (delete) memoria a variables y objetos. Sintaxis: – puntero a variable u objeto = new tipo; // crea una variable de tipo entero. – delete [ | puntero a variable u objeto; // borra objeto, [ | solo para matrices • • • • • • • • new devuelve un puntero al objeto si asignó memoria al objeto, en caso contrario devuelve 0 (en C++ el puntero nulo tiene valor 0 en lugar de NULL). Ej.: int * ptriContador = new int; char *ptrCar = new char [10|; ptrfFecha = new Date (24, 3, 1999); Ej.: delete ptriContador; delete [ | ptrCar; delete ptrsFecha; Delete no borra el puntero, borra el dato al que apunta el puntero. Delete solo se puede utilizar para objetos creados con new Solo se puede borrar un objeto con delete una sola vez Se puede aplicar delete al puntero nulo, sin problemas Función: Paso de parámetros • • • Por valor: – Declaración: void f1 (Estructipox xVar); – Invocación : f1 (xVar1); – Acceso: con .; xVar1. comp1 – Semantica: se copia la variable en el stack y de alli la obtiene la funcion. Si se modifica en la función no se refleja el cambio en el origen. – Uso: con tipos básicos. No eficiente con tipos complejos. Por puntero: – Declaración: void f1 (const Estructipox *xVar); – Invocación: f1 (&xVar1); – Acceso: con ->; xVar1-> comp1 – Semántica: La funcion obtiene la direccion de la variable. Si se modifica en la función se refleja el cambio en el origen. El puntero permanece cosntante. – Uso: con tipos complejos (estructuras , arrays,...) y parametro modificable. Por referencia:( significado de &: Referencia si hay un tipo delante de &; direccion de variable en otro caso) – Declaración: void f1 (const Estructipox &xVar); – Invocación: f1 (xVar); – Acceso: con .; xVar1. comp1 – Semántica: se copia la variable en el stack y de alli la obtiene la funcion. La funcion recibe un alias a la copia de la variable. Si se modifica en la función no se refleja el cambio en el origen. Simplicidad por el acceso con punto. – Uso: con tipos complejos y parametros no modificables. Función: Vuelta de valores • Por valor • Por puntero • Por referencia – Declaración: int & f1 () {return iVar;} – Invocación: i = f1 (); f1() = i; Vuelta del parámetro implícito this con funciones no estáticas miembro de clases. Otros conceptos • • • • • • • • • Macros y Constantes globales estilo C Macros y Constantes globales estilo C++ Directivas del Preprocesador Declaraciones, definiciones y referencias Tipos Variables y Objetos Inicialización Clases de almacenamiento Visibilidad Macros y Constantes globales estilo C • • • • • Definición: – Macros: Identificadores que representas sentencias o expresiones – Constantes simbólicas: Identificadores que representan constantes – Las macros y las constantes simbólicas se definen con la directiva: – #define identificadormacro cuerpomacro – El identificador no puede contener el carácter . – Ejemplo: #define PI 3.1416 Invocación: – Identificadores de macros en un programa se reemplaza por el cuerpo de la macro – Ejemplo: a= 34*PI; Macros predefinidas: – __FILE__ : • Macro que hace referencia el nombre del archivo fuente. • Se expande en una cadena que es el nombre del archivo entre comillas. (ej.: "fecha.h") Macro que es todo el archivo: – (con define e identificador de la macro) – Ej.: #define xx Macro de registro que es todo el archivo: – Cuando se genera una clase C++ con MS Developer Studio, usando el menú: Insert/New class, aparece una macro: • #define AFX_FECHA_H__10A52523_EC21_11D2_BC66_009027226902__INCLUDED_ • Macro que representa el registro del archivo FECHA.H para el registro de Windows. • El cuerpo de la macro es todo el contenido del archivo. Macros y Constantes globales estilo C++ • • • • C++ admite las Macros y Constantes globales estilo C En C++ las macros, se suelen sustituir por funciones inline. – Sobre las funciones inline, se realiza el chequeo de los tipos de parámetros, cosa que no ocurre con las macros, y por tanto no se producen efectos laterales indeseados. – Ejemplo: • #define Max (a,b) ( if (a>b) return a; return b;) // Max como macro en C • inline int Max (a,b){ if (a>b) return a; return b;} // Max como funcion inline en C++ Las constantes no se definen con la directiva define, sino con const. Ejemplo: – #define PI 3.1416 // constante del número pi en C; – const int PI = 3.1416; Directivas del preprocesador: • • • • • • • #if, #else, #endif (para compilación condicional) #ifdef, #ifndef (para definición condicional) #define, #undef (define o anula definición macro) #pragma token (soporte caracteristicas especificas del host) #include nombrearchivo (incluye archivo) #line nlinea, "nombrearchivo" (cambio nº linea y archivo) #error token (para terminar compilación) #If, #endif • • • • #ifdef identificador o if defined identificador #idndef identificador o #if !defined identificador #end if El identificador puede ser una macro. Ej.: __FILE_H__ • El identificador se puede pasar con la opción /D del compilador • Ej.: cl /Dtest fecha.ccp #Define • • • • • • #if !defined #define identificador cadena_de_tokens #endif // !defined Cuando no existe cadena de tokens, como ocurre en este caso, se anulan las ocurrencias del identificador, en el archivo fuente (fecha.cpp) Ejemplos: – #if !defined ( EXAMPLE_H) – #define EXAMPLE_H – Class Example – { – }; – #endif // !defined ( Example_H) – – – – – #if !defined(AFX_FECHA_H__10A52523_EC21_11D2_BC66_009027226902__INCLUDED_) #define AFX_FECHA_H__10A52523_EC21_11D2_BC66_009027226902__INCLUDED_ declaracion de la clase #endif // !defined(AFX_FECHA_H__10A52523_EC21_11D2_BC66_009027226902__INCLUDED_) Esto se hace para incluir un solo archivo fecha.h en fecha.cpp #Pragma • Directiva para indicar al compilador, caracteristicas especificas de la máquina. • #pragma once, especifica que el archivo actual(fecha.h) se incluira solo una vez. • Esto conviene ponerlo en todos los archivos .h • Ejemplo: – #if _MSC_VER >= 1000 – #pragma once – #endif // _MSC_VER >= 1000 #Include • Incluye el archivo archivo indicado. Si el nombre está entre < >, lo busca en el include del sistema. Si el nombre está entre " " lo busca en el directorio de trabajo. • Ejemplo: – #include <iostream.h> – #include "fecha.h" Declarativas en .h Cuando se genera una clase C++ (ej.: Fecha) con MS Developer Studio, usando el menú: Insert/New class, aparece al comienzo y al final del archivo .h generado: • // lo que sigue se traduce en "fecha.h" con el número de registro de Windows indicado. #if !defined(AFX_FECHA_H__588B7D25_0306_11D3_BC68_009027226902__INCLUDED_) • #define AFX_FECHA_H__588B7D25_0306_11D3_BC68_009027226902__INCLUDED_ • • • #if _MSC_VER >= 1000 #pragma once #endif // _MSC_VER >= 1000 • // Declaración de la clase • • // lo que sigue es el final de la declaracion de AFX_FECHA_H #endif // !defined(AFX_FECHA_H__588B7D25_0306_11D3_BC68_009027226902__INCLUDED_) Declaraciones, definiciones y referencias • • • • • • Declaración: Indica al compilador que un elemento del programa o un nombre existe. Pueden existir varias veces en un programa. – Signatura de una funcion: int f1 ( float x); – referencias externas: extern int i; Definición: Especifica al compilador que el código o el dato, que el nombre describe, existe. Solo existen una vez en un programa. Objeto, variable, funcion, clase o enumerador. Implantación de la función o definicion de su cuerpo: int f1 ( float x) { … } Declaraciones y definiciones simultáneas: int i; int j = 10; enumeracion y clases con implantacion de funciones Referencias (uso): – – expresiones : x = y; invocación de funciones: y = f1 (x); Tipos • • Fundamentales (con o sin signo: (char, short, int, long); con signo: (float, double, long double)) Derivados: – Simples: array [], funciones (), punteros *, referencia a objetos &, constantes const, punteros a miembros de una clase (., -> ::*, .*, ->*) – Redefinidos: • Nombres de tipos (typedef) ej: typedef unsigned char BYTE; • Enumeración (enum) Ej.: enum Color {rojo, verde, azul}; – Compuestos: • Estructuras (struct) Ej.: struct miEstru {int iVar; char chVar;}; • Uniones (union): Ej.: union miUnion {int iVar; char chVar;}; • Clases (class):Ej.: class Punto {public: Punto(); private: int x;}; Variables y objetos • Una variable es una instancia de un tipo clásico. Ej.: int iX; • Un objeto es una instancia de una clase. • Un objeto se puede crear/destruir: – Con los constructores/destructores de la clase – Con los operadores new/delete Inicialización • Las variables se inicializan en las declaraciones: – Ej.: int iX = 5; char chNombre [| = {"pepe"}; • Los objetos se inicializan al crearlos con los constructores de la clase: – Ej.: Persona pepe (Lopez, Jose, 24); Acceso a miembros de clases • Nombre del objeto: Acceso por . Ej.: spepe.Edad; pepe.Visualizad(); • Puntero al objeto: Acceso por -> Ej.: ptrPepe->Edad; ptrPepe->Visualizad(); Consideraciones varias • Cuando se borra un objeto puntero, no se pone a cero su puntero. • Si se crean varios objetos con new y se asignan al mismo puntero, ya no es posible acceder al anterior. • Ej.: Persona *ptrAmigo = new (Persona ("pepe"); • Persona *ptrAmigo = new (Persona ("juan"); • ptrAmigo = ptrAmigo.Persona ("luis"); Clases de almacenamiento (Vida) (tipos, variables, objetos y funciones) • • • • Automático (automatic) Estático (static) Registro (register) Externo (external) Visibilidad (scope) (tipos, variables, objetos y funciones) • • • • • Local a un bloque Visibilidad en archivo o módulo Visibilidad en función Visibilidad en la clase Visibilidad en prototipo de función