SlideShare una empresa de Scribd logo
1 de 33
Descargar para leer sin conexión
Una breve introducci´n a C++
                                o
                             V´
                              ıctor Mu˜oz
                                      n


Contenidos
1 Introducci´n
            o                                                                                                             3

2 Estructura b´sica de un programa
                a                                        en      C++                                                      3
  2.1 El programa m´s simple . . . . .
                     a                                   . .     . . . .         .   .   .   .   .   .   .   .   .   .    3
  2.2 Definici´n de funciones . . . . . .
              o                                          . .     . . . .         .   .   .   .   .   .   .   .   .   .    4
  2.3 Nombres de variables . . . . . . .                 . .     . . . .         .   .   .   .   .   .   .   .   .   .    4
  2.4 Tipos de variables . . . . . . . . .               . .     . . . .         .   .   .   .   .   .   .   .   .   .    4
  2.5 Ingreso de datos desde el teclado                  . .     . . . .         .   .   .   .   .   .   .   .   .   .    6
  2.6 Operadores aritm´ticos . . . . . .
                        e                                . .     . . . .         .   .   .   .   .   .   .   .   .   .    6
  2.7 Operadores relacionales . . . . . .                . .     . . . .         .   .   .   .   .   .   .   .   .   .    7
  2.8 Asignaciones . . . . . . . . . . . .               . .     . . . .         .   .   .   .   .   .   .   .   .   .    7
  2.9 Conversi´n de tipos . . . . . . . .
               o                                         . .     . . . .         .   .   .   .   .   .   .   .   .   .    8

3 Control de flujo                                                                                                         9
  3.1 if, if... else, if...             else if              .   .   .   .   .   .   .   .   .   .   .   .   .   .   .    9
  3.2 Expresi´n condicional . .
             o                      .    . . . . .           .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   10
  3.3 switch . . . . . . . . . .    .    . . . . .           .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   10
  3.4 while . . . . . . . . . .     .    . . . . .           .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   11
  3.5 for . . . . . . . . . . . .   .    . . . . .           .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   11
  3.6 do... while . . . . . .       .    . . . . .           .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   12
  3.7 goto . . . . . . . . . . .    .    . . . . .           .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   12

4 Funciones                                                                                                              12
  4.1 Funciones tipo void . . .          .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   12
  4.2 return . . . . . . . . . . .       .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   12
  4.3 Funciones con par´metros
                        a                .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   13
  4.4 Par´metros default . . . .
         a                               .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   15

                                             1
4.5   Alcance, visibilidad, tiempo de vida . . . . . . . . . . . . . . . 16
   4.6   Recursi´n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
                o

5 Matrices                                                                                             17
  5.1 Declaraci´n e inicializaci´n . . . . . . . .
               o                o                      .   .   .   .   .   .   .   .   .   .   .   .   17
  5.2 Matrices como par´metros de funciones .
                         a                             .   .   .   .   .   .   .   .   .   .   .   .   18
  5.3 Matrices multidimensionales . . . . . . .        .   .   .   .   .   .   .   .   .   .   .   .   19
  5.4 Matrices de caracteres: cadenas (strings)        .   .   .   .   .   .   .   .   .   .   .   .   19
      5.4.1 string.h . . . . . . . . . . . . . .       .   .   .   .   .   .   .   .   .   .   .   .   20
      5.4.2 Input/Output de cadenas . . . .            .   .   .   .   .   .   .   .   .   .   .   .   20

6 Clases                                                                                               21
  6.1 Definici´n . . . . . . . . . . . . . . . .
             o                                     .   .   .   .   .   .   .   .   .   .   .   .   .   23
  6.2 Miembros . . . . . . . . . . . . . . . .     .   .   .   .   .   .   .   .   .   .   .   .   .   23
  6.3 Miembros p´blicos y privados . . . . .
                 u                                 .   .   .   .   .   .   .   .   .   .   .   .   .   24
  6.4 Operador de selecci´n (.) . . . . . . . .
                          o                        .   .   .   .   .   .   .   .   .   .   .   .   .   25
  6.5 Implementaci´n de funciones miembros
                   o                               .   .   .   .   .   .   .   .   .   .   .   .   .   26
  6.6 Constructor . . . . . . . . . . . . . . .    .   .   .   .   .   .   .   .   .   .   .   .   .   26
  6.7 Destructor . . . . . . . . . . . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   28
  6.8 Matrices de clases . . . . . . . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   29

7 Sobrecarga                                                               29
  7.1 Sobrecarga de funciones . . . . . . . . . . . . . . . . . . . . . 29
  7.2 Sobrecarga de operadores . . . . . . . . . . . . . . . . . . . . . 30
  7.3 Coerci´n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
            o

8 Punteros                                                                                             31

9 Herencia                                                                                             32




                                      2
1     Introducci´n
                o
Estos apuntes corresponden a un peque˜o intento de ordenar los temas
                                          n
abordados en el curso de Computaci´n para Matem´ticos dictado el Primer
                                      o              a
Semestre de 1998. No pretendo que sean tomados muy en serio, en el sen-
tido que est´n dise˜ados para satisfacer las m´
            a       n                           ınimas necesidades del curso,
sirviendo como un ayuda-memoria de los t´picos abordados, para futura
                                              o
referencia. No se consideran todas las posibilidades del lenguaje, y las ex-
plicaciones est´n reducidas al m´
               a                 ınimo o est´n ausentes del todo, de modo
                                             a
que creo son m´s utiles para quienes ya sepan algo de C++ (idealmente los
                a ´
alumnos del curso una vez terminado ´ste) y quieran recordar alg´n detalle
                                        e                          u
de sintaxis ya olvidado. Tambi´n pueden servir para personas con alguna
                                e
experiencia en otros lenguajes de programaci´n y que deseen comenzar el
                                                o
aprendizaje de C++. El mundo est´ lleno de manuales a los cuales se puede
                                    a
acudir en caso de urgencias m´s elevadas. S´lo el Tiempo y mi tiempo dir´n
                              a             o                             a
si estos apuntes ser´n extendidos alguna vez.
                    a


2     Estructura b´sica de un programa en C++
                  a
2.1    El programa m´s simple
                    a
El primer ejemplo de todo manual es el que permite escribir “Hola” en la
pantalla del computador.

#include <iostream.h>
void main()
{
    cout << "Hola." << endl;
}

   La primera l´
               ınea define las instrucciones adecuadas para enviar luego
un mensaje a pantalla. La funci´n main es donde comienza a ejecutarse el
                               o
programa; siempre debe haber una funci´n main en nuestro programa. cout
                                      o
env´ el mensaje a pantalla, y endl agrega un cambio de l´
   ıa                                                    ınea al final del
mensaje.




                                     3
2.2    Definici´n de funciones
              o
Uno puede delegar la impresi´n del mensaje anterior a una funci´n indepen-
                            o                                  o
diente:

#include <iostream.h>

void PrintHola()
{
    cout << "Hola." << endl;
}

void main()
{
    PrintHola();
}

2.3    Nombres de variables
   – Deben comenzar con una letra (may´sculas y min´sculas son distintas).
                                      u            u

   – Pueden contener n´meros.
                      u

   – Pueden contener el s´
                         ımbolo _ (underscore).

   – Longitud arbitraria.

   – No pueden corresponder a una de las 48 palabras reservadas de C++
     (if, else, etc.).

2.4    Tipos de variables
Todas las variables a usar deben ser declaradas de acuerdo a su tipo. Por
ejemplo, si usamos una variable i que sea un n´mero entero, debemos, antes
                                              u
de usarla, declararla, y s´lo entonces podemos asignarle un valor:
                          o

int i;
i=10;



                                    4
Es posible reunir las acciones de declaraci´n e inicializaci´n en una misma
                                               o                o
l´
 ınea:

int i = 10;

       Los tipos de variables disponibles son1 :
        int                 Enteros entre −215 = −32768 y 215 − 1 = 32767
                            o entre −231 = −2147483648 y 231 − 1 = 2147483647
        short int
        short               Enteros entre −215 y 215 − 1.
        long int
        long           Enteros entre −231 y 231 − 1.
        unsigned int   Enteros entre 0 y 216 − 1
                       o entre 0 y 232 − 1.
        unsigned short Enteros entre 0 y 216 − 1.
        unsigned long  Enteros entre 0 y 232 − 1.
        char           Caracteres.
        float          Reales en los intervalos [−1.7 · 1038 , −0.29 · 10−38 ],
                       [0.29 · 10−38 , 1.7 · 1038 ]
                       (Precisi´n de unos 7 d´
                                o                   ıgitos decimales.)
        double         Reales en los mismos intervalos que float,
                       pero con precisi´n de 16 decimales,
                                          o
                       o en los intervalos [−0.9 · 10308 , −0.86 · 10−308 ]
                       y [0.86 · 10−308 , 0.9 · 10308 ], con precisi´n de
                                                                    o
                       15 decimales.
   Las variables tipo char alojan caracteres, debiendo inicializarse en la
forma:

char c = ’a’;

    Adem´s de las letras may´sculas y min´sculas, y s´
          a                    u             u            ımbolos como &, (,
:, etc., hay una serie de caracteres especiales (caracteres de escape) que es
posible asignar a una variable char. Ellos son:
   1
   Los valores de los rangos indicados son simplemente representativos y dependen de la
m´quina utilizada.
 a




                                          5
newline           n
      horizontal tab    t
      vertical tab      v
      backspace         b
      carriage return   r
      form feed         f
      alert (bell)      a
      backslash         
      single quote      ’
      double quote      "
    Por ejemplo, la l´
                     ınea:

cout << "Primera columnat Segunda columnan
          Segunda linea" << endl;

corresponde al output

Primera columna              Segunda columna
Segunda linea

2.5       Ingreso de datos desde el teclado
#include <iostream.h>
void main()
{
    int i;
    cout << "Ingrese un numero entero: ";
    cin >> i;
    cout << "El numero ingresado fue: " << i << endl;
}

2.6       Operadores aritm´ticos
                          e
Existen operadores para la suma, la resta, la multiplicaci´n, la divisi´n:
                                                          o            o

+     -    *   /




                                      6
2.7      Operadores relacionales
Los s´ımbolos para las relaciones de igualdad, desigualdad, menor, menor o
igual, mayor y mayor o igual son:
==       !=           <        <=        >   >=
     Para las relaciones l´gicas AND, OR y NOT:
                          o
&&       ||       !

2.8      Asignaciones
     a) Asignaci´n simple.
                o

        i = 1;

     b) Asignaci´n compuesta.
                o
        La expresi´n
                  o

        x = x + 2

        se puede reemplazar por
        x += 2
        Existen los operadores
        +=       -=       *=        /=
     c) Operadores de incremento y decremento.
        La expresi´n
                  o
        x = x + 1
        se puede reescribir
        x += 1
        o bien
        x++
        An´logamente, existe el operador --.
          a

                                             7
2.9    Conversi´n de tipos
               o
Observemos que en una expresi´n del tipo:
                             o
int i = 3;
float x = 43.8;
cout << "Suma = " << x + i << endl;
el computador debe sumar dos variables de tipos distintos, y por tanto debe
convertir ambas a un tipo com´n antes de efectuar la suma. Existen dos
                              u
modos de proceder:

  a) Conversi´n expl´
             o      ıcita.
      Insertar la expresi´n
                         o

      j = float(i);

      Esto es bastante tedioso, por cuanto el programador debe realizar el
      trabajo de conversi´n personalmente.
                         o

  b) Conversi´n impl´
             o      ıcita.
      El compilador realiza las conversiones de modo autom´tico, prefiriendo
                                                          a
      siempre la conversi´n desde un tipo de variable de menor precisi´n a
                         o                                             o
      uno de mayor precisi´n (de int a double, de short a int, etc.).
                           o
      Es interesante notar c´mo las conversiones impl´
                            o                         ıcitas de tipos pueden
      tener consecuencias insospechadas y esot´ricas.
                                              e
      Consideremos las tres expresiones:

        i) x = (1/2) * (x + a/x) ;
       ii) x = (0.5) * (x + a/x) ;
       iii) x = (x + a/x)/2 ;

      Si inicialmente x=0.5 y a=0.5, por ejemplo, i) entrega el valor x=0,
      mientras ii) y iii) entregan el valor x=1.5. Lo que ocurre es que 1 y
      2 son enteros, de modo que 1/2 = 0. De acuerdo a lo que dijimos,
      uno esperar´ que en i), como conviven n´meros reales con enteros, los
                  ıa                            u
      n´meros enteros fueran convertidos a reales y, por tanto, la expresi´n
       u                                                                  o
      tuviera el resultado esperado, 1.5. El problema es la prioridad de las

                                     8
operaciones. No todas las operaciones tienen igual prioridad (las mul-
      tiplicaciones y divisiones se realizan antes que las sumas y restas, por
      ejemplo), y esto permite al compilador decidir cu´l operaci´n efectuar
                                                         a        o
      primero. Cuando se encuentra con operaciones de igual prioridad (dos
      multiplicaciones, por ejemplo), se procede a efectuarlas de izquierda a
      derecha.
      Pues bien, en i), la primera operaci´n es 1/2, una divisi´n entre en-
                                            o                      o
      teros, i.e. cero. En ii) no hay problema, porque todas son operaciones
      entre reales. Y en iii) la primera operaci´n es el par´ntesis, que es una
                                                o           e
      operaci´n entre reales. Al dividir por 2 ´ste es convertido a real antes
              o                                 e
      de calcular el resultado.
      i) a´n podr´ utilizarse, cambiando el prefactor del par´ntesis a 1.0/2.0,
          u      ıa                                          e
      una pr´ctica que ser´ conveniente adoptar como standard cuando quer-
             a            ıa
      emos utilizar enteros dentro de expresiones reales, para evitar errores
      que pueden llegar a ser muy oscuros.


3     Control de flujo
3.1    if, if...       else, if...        else if
    a) if (a==b)
       {
           cout << "a es igual a b" << endl;
       }

    b) if (c!=d)
       {
           cout << "c es distinto de d" << endl;
       }
       else
       {
           cout << "c es igual a d" << endl;
       }

    c) if (e > f)
       {
           cout << "e es mayor que f" << endl;


                                      9
}
      else if (e == f)
      {
          cout << "e es igual a f" << endl;
      }
      else
      {
          cout << "e es menor que f" << endl;
      }

3.2    Expresi´n condicional
              o
if (a==b)
{
    c = 1;
}
else
{
    c = 0;
}

se puede reemplazar por

c = (a==b) ? 1 : 0;

3.3    switch
switch (i)
{
case 1:
     {
         cout << "Caso 1." << endl;
     }
     break;
case 2:
     {
         cout << "Caso 2." << endl;
     }


                               10
break;
default:
     {
         cout << "Otro caso." << endl;
     }
     break;
}

    La instrucci´n break permite que la ejecuci´n del programa salte a la
                o                                 o
l´
 ınea siguiente despu´s de la serie de instrucciones asociadas a switch. Por
                      e
ejemplo, si no existieran los break, e i=1, entonces ver´
                                                        ıamos en pantalla las
l´
 ıneas Caso 1., Caso 2. y Otro caso. La instrucci´n default es opcional.
                                                      o

3.4    while
while (i < 3)
{
    cout << i << endl;
    i++;
}

3.5    for
for (i = 1; i < 10; i++)
{
    cout << "Valor del indice: " << i << endl;
}

  Los argumentos segundo y tercero de for son opcionales (no los ;).
Adem´s, se puede involucrar m´s de una variable en el ciclo:
    a                        a

for (i=0, k=20; (i<10) && (k<100); i++, k+=6)
{
    cout << "i + k = " << i + k << endl;
}




                                     11
3.6    do...     while
do
{
      cout << i << endl;
      i++;
}
while (i<=20);

3.7    goto
Existe tambi´n en C++ una instrucci´n goto que permite saltar de un punto
             e                     o
a otro del programa (goto salto; permite saltar a la l´
                                                      ınea que contiene la
instrucci´n salto:). Sin embargo, se considera una mala t´cnica de pro-
         o                                                  e
gramaci´n usar goto, y siempre se puede dise˜ar un programa evit´ndolo.
        o                                   n                     a
Altamente no recomendable.


4     Funciones
Las funciones nos permiten programar partes del procedimiento por separado.
Un ejemplo simple de ellas lo vimos en la subsecci´n 2.2.
                                                  o

4.1    Funciones tipo void
Un caso especial de funciones es aqu´l en que el programa que llama la funci´n
                                    e                                       o
no espera que ´sta le entregue ning´n valor al terminar. Por ejemplo, en la
               e                    u
subsecci´n 2.2, la funci´n PrintHola simplemente imprime un mensaje en
         o               o
pantalla. El resto del programa no necesita de ning´n resultado parcial
                                                        u
proveniente de la ejecuci´n de dicha funci´n. La definici´n de estas funciones
                         o                 o             o
debe ir precedida de la palabra void, como en el ejemplo citado. Observemos
que la funci´n main en todos nuestros ejemplos hasta ahora es una funci´n
            o                                                               o
de tipo void tambi´n.
                    e

4.2    return
Si deseamos definir una funci´n que calcule una ra´ cuadrada, evidente-
                              o                     ız
mente esperamos que la funci´n nos entregue un resultado: el valor de la ra´
                            o                                              ız


                                     12
cuadrada. En este caso hay que traspasar el valor de una variable desde la
funci´n al programa que la llam´. Esto se consigue con return.
     o                         o

int numero()
{
    int i = 3;
    return i;
}

void main()
{
    cout <<    "Llamamos a la funcion" << endl;
    cout <<    "El numero es: " << numero() << endl;
    int i =    5;
    i = i +    numero();
    cout <<    "El numero mas 5 es: " << i << endl;
}

    En este caso, la funci´n simplemente entrega el valor de la variable interna
                          o
i, es decir 3, el cual puede ser usado para salida en pantalla o dentro de
operaciones matem´ticas corrientes.
                     a
    Dos observaciones utiles:
                        ´

  a) La declaraci´n de la funci´n lleva antepuesto el tipo de variable que
                  o             o
     la funci´n entrega. En el ejemplo, la variable entregada es un entero,
             o
     i, y la declaraci´n debe ser por tanto: int numero(). Podemos tener
                      o
     funciones tipo double, char, long, etc., de acuerdo al tipo de variable
     que corresponde a return.

  b) La variable i que se usa dentro de main() y la que se usa dentro de
     numero() son distintas. A pesar de que tienen el mismo nombre, se
     pueden usar independientemente como si se llamaran distinto. Se dice
     que i es una variable local.

4.3    Funciones con par´metros
                        a
Volviendo al ejemplo de la ra´ cuadrada, nos gustar´ llamar a esta funci´n
                             ız                    ıa                   o
con un par´metro (el n´mero al cual se le va a calcular la ra´ cuadrada).
           a           u                                     ız
Existen dos modos de transferir par´metros a una funci´n:
                                   a                  o

                                      13
a) Por valor.

   int funcion(int i)
   {
       i+=4;
       return i;
   }

   void main()
   {
       i = 3;
       cout << "El valor de la funcion es " << funcion(i)
            << endl;
       cout << "El valor del parametro es " << i << endl;
   }

   El resultado en pantalla es:

   El valor de la funcion es 7
   El valor del parametro es 3

   La funci´n funcion entrega el valor del par´metro m´s 4. Usamos
             o                                    a         a
   el mismo nombre (i) para las variables en main y funcion, pero son
   variables locales, as´ que no interfieren. Lo importante es notar que
                        ı
   cuando se llama la funci´n, la reasignaci´n del valor de i [i+=4] ocurre
                            o               o
   s´lo para la variable local en funcion; el par´metro externo mantiene
    o                                            a
   su valor.
   Lo que ha ocurrido es que la funci´n copia el valor de la variable externa
                                     o
   i en una nueva variable (que tambi´n se llama i, pero est´ en otra
                                         e                         a
   direcci´n de memoria). El valor con el que trabaja la funci´n es la
          o                                                          o
   copia, manteniendo inalterada la variable original.

b) Por referencia.

   int funcion(int & i)
   {
       i+=4;

                                   14
return i;
      }

      void main()
      {
          i = 3;
          cout << "El valor de la funcion es " << funcion(i)
               << endl;
          cout << "El valor del parametro es " << i << endl;
      }

      ´
      Este es el mismo ejemplo anterior, pero modificando la declaraci´n del
                                                                       o
      argumento en funcion. El efecto es que en vez de traspasarle a funcion
      el valor del par´metro, se le entrega la direcci´n de memoria de dicha
                      a                               o
      variable, permiti´ndosele de este modo modificar su valor. El resultado
                        e
      en pantalla del ultimo programa ser´:
                      ´                    a

      El valor de la funcion es 7
      El valor del parametro es 7

      El paso de par´metros por referencia debe ser usado con sabidur´
                       a                                                    ıa.
      De hecho el ejemplo presentado es poco recomendable. Un caso m´s       a
      util es el intercambiar entre s´ el valor de dos variables, digamos a1=1
      ´                              ı
      y a2=3. Luego de ejecutar la funci´n queremos que a1=3 y a1=1, es
                                            o
      decir, precisamente que el valor de las variables originales cambie. El
      uso de par´metros por referencia es la t´cnica a usar en esta situaci´n.
                  a                             e                          o

4.4       Par´metros default
             a
C++ permite que omitamos algunos par´metros de la funci´n llamada, la
                                         a                 o
cual reemplaza los valores omitidos por otros predeterminados. Tomemos
por ejemplo la funci´n de la subsecci´n 4.3, y modifiqu´mosla de modo que
                    o                o                e
si no le entregamos par´metros, asuma que el n´mero entregado fue 5:
                       a                       u

int funcion(int i = 5)
{
    i+=4;


                                      15
return i;
}

void main()
{
    cout << "El resultado default es " << funcion() << endl;
    int i = 3;
    cout << "Cuando el parametro vale " << i <<
            " el resultado es " << funcion(i) << endl;
}

    El output correspondiente es:

El resultado default es 9
Cuando el parametro vale 3 el resultado es 7

4.5    Alcance, visibilidad, tiempo de vida
Con el concepto de funci´n hemos apreciado que es posible que coexistan
                          o
variables con el mismo nombre en puntos distintos del programa, y que sig-
nifiquen cosas distintas. Conviene entonces tener en claro tres conceptos que
est´n ligados a esta propiedad:
   a

Alcance La secci´n del c´digo durante la cual el nombre de una variable
                 o       o
    puede ser usado. Comprende desde la declaraci´n de la variable hasta
                                                    o
    el final del cuerpo de la funci´n donde es declarada.
                                  o
      Si la variable es declarada dentro de una funci´n es local . Si es definida
                                                      o
      fuera de todas las funciones (incluso fuera de main), la variable es global.

Visibilidad Indica cu´les de las variables actualmente al alcance pueden ser
                      a
     accesadas. En nuestros ejemplos (subsecci´n 4.3), la variable i en main
                                                o
     a´n est´ al alcance dentro de la funci´n funcion, pero no es visible, y
      u     a                               o
     por eso es posible reutilizar el nombre.

Tiempo de vida Indica cu´ndo las variables son creadas y cu´ndo destru-
                           a                                    a
    idas. En general este concepto coincide con el alcance (las variables son
    creadas cuando son declaradas y destruidas cuando la funci´n dentro de
                                                                o
    la cual fueron declaradas termina), salvo porque es posible definir: (a)
    variables din´micas, que no tienen alcance, sino s´lo tiempo de vida;
                 a                                      o

                                       16
(b) variables est´ticas, que conservan su valor entre llamadas sucesivas
                       a
      de una funci´n (estas variables tienen tiempo de vida mayor que su
                    o
      alcance).

4.6    Recursi´n
              o
C++ soporta un tipo especial de t´cnica de programaci´n, la recursi´n, que
                                 e                    o            o
permite que una funci´n se llame a s´ misma. Esto permite definir de modo
                     o              ı
muy compacto una funci´n que calcule el factorial de un n´mero entero n.
                       o                                 u

int factorial(int n)
{
    return (n<2) ? 1: n * factorial(n-1);
}


5     Matrices
5.1    Declaraci´n e inicializaci´n
                o                o
Podemos declarar (e inicializar inmediatamente) matrices de enteros, reales
de doble precisi´n, caracteres, etc., seg´n nuestras necesidades.
                o                        u

int a[5];
double r[3] = {3.5, 4.1, -10.8};
char palabra[5];

   Una vez declarada la matriz (digamos a[5]), los valores individuales se
accesan con a[i], con i desde 0 a 4. Por ejemplo, podemos inicializar los
elementos de la matriz as´
                         ı:

a[0] = 3;
a[3] = 5; ...

o si queremos ingresarlos desde el teclado:

for (i = 0; i < 5; i++)
{
    cin >> a[i];
}

                                     17
Y si deseamos escribirlos en pantalla:

for (i = 0; i < 5; i++)
{
    cout >> a[i];
}

5.2    Matrices como par´metros de funciones
                        a
Si deseamos, por ejemplo, dise˜ar una funci´n que mande los elementos de
                              n            o
una matriz a pantalla:

void PrintMatriz(int i, double a[])
{
     for (int j = 0; j < i; j++)
     {
          cout << "Elemento " << j << " = " << a[j] << endl;
     }
}

void main()
{
     double matriz[5] = {3.5, 5.2, 2.4, -0.9, -10.8};
     PrintMatriz(5, matriz);
}

    Observemos que la funci´n debe recibir dos par´metros, uno de los cuales
                           o                      a
es la dimensi´n de la matriz. Esto se debe a que cuando las matrices son
             o
usadas como par´metros la informaci´n de su dimensi´n no es traspasada,
                a                    o                o
y debe ser comunicada independientemente. Una ligera optimizaci´n al pro-
                                                                 o
grama anterior es modificar main a:

void main()
{
     int dim = 5;
     double matriz[dim] = {3.5, 5.2, 2.4, -0.9, -10.8};
     PrintMatriz(dim, matriz);
}


                                     18
De este modo, si eventualmente cambiamos de opini´n y deseamos trabajar
                                                    o
con matrices de longitud distinta, s´lo hay que modificar una l´
                                    o                         ınea de c´digo
                                                                       o
(la primera) en todo el programa, el cual puede llegar a ser bastante largo
por cierto. (En el ejemplo, tambi´n habr´ que cambiar la l´
                                   e       ıa                ınea de inicial-
izaci´n de la matriz, porque asume que la matriz requiere s´lo 5 elementos,
     o                                                     o
pero de todos modos deber´ ser clara la enorme conveniencia —en progra-
                           ıa
mas m´s generales— de definir la dimensi´n de la matriz como una variable
       a                                   o
independiente.)

5.3    Matrices multidimensionales
Es f´cil declarar e inicializar matrices de m´s de una dimensi´n:
    a                                        a                o
double array[10][8];
int array[2][3] = {{1, 2, 3},
                   {4, 5, 6}};

5.4    Matrices de caracteres: cadenas (strings)
Una cadena es una matriz de caracteres que termina con el char nulo: ’0’.
char palabra[5] = {’H’, ’o’, ’l’, ’a’, ’0’};
Cuando enviamos esta matriz a pantalla:
for (i = 0; i < 5; i++)
{
    cout << palabra[i];
}
El resultado es Hola. Es equivalente esto a la instrucci´n ya conocida
                                                        o
cout << "Hola". De hecho, la declaraci´n de palabra podr´ haberse es-
                                      o                   ıa
crito:
char palabra[5] = "Hola";
    Las l´
         ıneas de texto, entonces, no corresponden sino a matrices de car-
acteres. Se entiende entonces la necesidad de introducir el char especial
’0’. En efecto, toda matriz en C++ debe tener una dimensi´n definida.
                                                                  o
Sin embargo, las palabras o las l´
                                 ıneas de texto que se nos pudiera ocurrir uti-
lizar pueden tener una longitud arbitraria, lo cual genera un conflicto. C++
resuelve el problema aceptando que estas matrices de caracteres tengan lon-
gitud arbitraria, pero adoptando la convenci´n de se˜alar d´nde terminan.
                                              o        n     o

                                      19
5.4.1   string.h
Una serie de funciones utiles para manejar palabras (convertir todas las letras
                       ´
en may´sculas, contar el n´mero de caracteres, etc.) son accesibles agregando
       u                   u
al comienzo del programa la l´ ınea:
#include <string.h>
   Por ejemplo:
  a) strlen(a) entrega el n´mero de caracteres de la cadena a (como un
                           u
     humano lo entender´ es decir, sin incluir ’0’).
                       ıa,
  b) strncpy(a,b) copia la cadena b en a. (Podr´   ıamos esperar que, como
     cuando intervienen variables num´ricas, esto se realizara con a=b, pero
                                     e
     no es as´
             ı.)

5.4.2   Input/Output de cadenas
Ya sabemos que la salida a pantalla de cadenas se realiza con cout y <<
simplemente, como con todos los dem´s tipos de variables.
                                       a
   El ingreso por teclado de cadenas es m´s problem´tico debido a la longitud
                                         a         a
indeterminada de la matriz. La soluci´n m´s f´cil es:
                                       o    a a
char a[30];
cout << "Ingrese una palabra: ";
cin >> a;
La idea es que la matriz sea suficientemente grande (30 caracteres en este
caso) para que una palabra cualquiera quepa holgadamente. Las dificultades
que aparecen son dos:
  a) La longitud del input puede ser demasiado grande. El problema de esto
     es que un input demasiado grande aloja caracteres en direcciones de
     memoria sobre los cuales no se tiene ningun control, con consecuencias
     posiblemente catastr´ficas en aplicaciones suficientemente complicadas.
                         o
     La soluci´n ser´ aumentar el tama˜o de la matriz (lo cual no se puede
              o     ıa                  n
     hacer hasta infinito en todo caso).
  b) S´lo se puede ingresar una palabra a la vez. Esto es porque C++ con-
       o
     sidera a los espacios en blanco como fin de input. Esto no es necesari-
     amente una desventaja, porque si queremos ingresar por teclado varios

                                      20
valores de una sola vez, basta separarlos por espacios. Pero cuando se
     trata de texto no necesariamente queremos ingresar palabras individ-
     uales.
   Una soluci´n al problema b) es ingresar l´
               o                              ıneas completas (i.e. hasta que
aparezca un ’n’ o Enter). Claro que esto no soluciona el problema del
control de la longitud del texto (una l´
                                       ınea podr´ ser m´s larga que cualquier
                                                ıa     a
longitud preconcebida), problema que debe ser tratado por separado.
   El siguiente programa muestra un ejemplo de soluci´n para ambas situa-
                                                        o
ciones:
int buffersize = 512;
char inputBuffer[buffersize];
if (cin.getline(inputBuffer,buffersize-1))
{
     cout << inputBuffer << endl;
}
else
{
    cout << "Demasiado larga: " << inputBuffer << endl;
    while (cin.clear(), !cin.getline(inputBuffer, buffersize-1))
    {
        cout << " y tambien: " << inputBuffer << endl;
    }
    cout << " y finalmente: " << inputBuffer << endl;
}
    En este programa, cin.getline(inputBuffer,buffersize) recibe una
l´
 ınea desde el teclado hasta que encuentra un fin de l´ ınea, con un m´ximo
                                                                      a
de buffersize-1 caracteres, a˜adiendo al final un ’0’. Esta funci´n es
                                 n                                     o
falsa si algo sali´ mal en el proceso de ingreso de datos (por ejemplo, si se
                  o
ingresaron m´s caracteres que la longitud establecida).
              a
    cin.clear() resetea el estado del mecanismo de input, prepar´ndolo para
                                                                 a
una nueva sesi´n de ingreso.
                o


6    Clases
C++ dispone de una serie de tipos de variables con los cuales nos est´ per-
                                                                     a
mitido operar: int, double, char, etc. Creamos variables de estos tipos y

                                     21
luego podemos operar con ellos:

int     x, y;
x =     3;
y =     6;
int     z = x + y;

    No hay, sin embargo, en C++, una estructura predefinida que corre-
sponda a n´meros complejos, vectores de dimensi´n n o matrices, por ejem-
          u                                    o
plo. Y sin embargo, nos agradar´ disponer de n´meros complejos que
                                  ıa              u
pudi´ramos definir como
     e
z = (3,5);
w = (6,8);
y que tuvieran sentido las expresiones
a   =   z + w;
b   =   z * w;
c   =   z / w;
d   =   z + 3;
e   =   modulo(z);
f   =   sqrt(z);
    Todas estas expresiones son completamente naturales desde el punto de
vista matem´tico, y ser´ bueno que el lenguaje las entendiera. Esto es
              a            ıa
imposible en el estado actual, pues, por ejemplo, el signo + es un operador que
espera a ambos lados suyos un n´mero. Sumar cualquier cosa con cualquier
                                    u
cosa no significa nada necesariamente, as´ que s´lo est´ permitido operar
                                              ı       o      a
con n´meros. Pero los humanos sabemos que los complejos son n´meros.
      u                                                                 u
¿C´mo dec´
   o        ırselo al computador? ¿C´mo convencerlo de que sumar vectores
                                        o
o matrices es tambi´n posible matem´ticamente, y que el mismo signo +
                       e                   a
deber´ servir para todas estas operaciones?
      ıa
    La respuesta es: a trav´s del concepto de clases. Lo que debemos hacer
                              e
es definir una clase de n´meros complejos. Llam´mosla Complejo. Una
                            u                           e
vez definida correctamente, Complejo ser´ un tipo m´s de variable que el
                                              a            a
compilador reconocer´, igual que int, double, char, etc. Y ser´ tan f´cil
                        a                                            a      a
operar con los Complejos como con todos los tipos de variables preexistentes.
Esta facilidad es la base de la extensibilidad de que es capaz C++, y por tanto
de todas las propiedades que lo convierten en un lenguaje muy poderoso.

                                      22
Las clases responden a la necesidad del programador de construir objetos
o tipos de datos que respondan a sus necesidades. Si necesitamos trabajar
con vectores de 5 coordenadas, ser´ natural definir una clase que corresponda
                                    a
a vectores con 5 coordenadas; si se trata de un programa de administraci´n de
                                                                         o
personal, la clase puede corresponder a un empleado, con sus datos personales
como elementos.
    Si bien es cierto uno puede trabajar con clases en el contexto de ori-
entaci´n al procedimiento, las clases muestran con mayor propiedad su po-
       o
tencial con la orientaci´n al objeto, donde cada objeto corresponde a una
                         o
clase. Por ejemplo, para efectuar una aplicaci´n para Windows, la ventana
                                                 o
principal, las ventanas de los archivos abiertos, la barra de men´, las cajas
                                                                   u
de di´logo, los botones, etc., cada uno de estos objetos estar´ asociado a una
     a                                                        a
clase.

6.1      Definici´n
                o
Digamos que queremos una clase para representar los empleados de una em-
presa. Llam´mosla Persona. La convenci´n aceptada es que los nombres de
             e                           o
las clases comiencen con may´scula. Esto es porque las clases, recordemos,
                             u
corresponder´n a tipos de variables tan v´lidos como los internos de C++
              a                           a
(int, char, etc.). Al usar nombres con may´scula distiguimos visualmente
                                             u
los nombres de un tipo de variable interno y uno definido por el usuario.
    La estructura m´
                   ınima de la definici´n de la clase Persona es:
                                       o

class Persona
{

};

     Todas las caracter´
                       ısticas de la clase se definen entre los parent´sis cursivos.
                                                                     e

6.2      Miembros
Se denomina miembros de una clase a todas las variables y funciones declaradas
dentro de una clase. Por ejemplo, para personas, es natural caracterizarlas
por su nombre y su edad. Y si se trata de empleados de una empresa, es
natural tambi´n tener una funci´n que entregue su sueldo:
             e                 o



                                        23
class Persona
{
     char nombre[20];
     int edad;
     double sueldo();
}

   Los miembros de una funci´n pueden tener cualquier nombre, excepto el
                              o
nombre de la propia clase dentro de la cual se definen.

6.3    Miembros p´ blicos y privados
                 u
Una clase distingue informaci´n (datos o funciones) privada (accesible s´lo a
                               o                                          o
otros miembros de la misma clase) y p´blica (accesible a funciones externas
                                         u
a la clase). La parte privada corresponde a la estructura interna de la clase,
y la parte p´blica a la implementaci´n (t´
             u                        o     ıpicamente funciones), que permite
la interacci´n de la clase con el exterior.
            o
    Consideremos ahora nuestro deseo de tener una clase que represente
n´meros complejos. Un n´mero complejo tiene dos n´meros reales (parte
  u                         u                             u
real e imaginaria), y ´sos son elementos privados —es decir, parte de su es-
                       e
tructura interna. Sin embargo, nos gustar´ poder modificar y conocer esas
                                              ıa
cantidades. Eso s´lo puede hacerse a trav´s de funciones p´blicas.
                  o                          e               u

class Complejo
{
private:
    double real, imaginaria;
public:
    void setreal(double);
    void setimag(double);
    double getreal();
    double getimag();
};

En este ejemplo, los miembros privados son s´lo variables, y los miembros
                                                 o
 u            o              ´
p´blicos son s´lo funciones. Este es el caso t´
                                              ıpico, pero puede haber variables
y funciones de ambos tipos.



                                      24
6.4    Operador de selecci´n (.)
                          o
Hemos definido una clase de n´meros complejos y funciones que nos per-
                              u
miten conocer y modificar las partes real e imaginaria. ¿C´mo se usan estos
                                                         o
elementos? Consideremos el siguiente programa de ejemplo:

class Complejo
{
private:
    double real, imaginaria;
public:
    void setreal(double);
    void setimag(double);
    double getreal();
    double getimag();
};

void main()
{
    Complejo z, w;

      z.setreal(3);
      z.setimag(2.8);
      w.setreal(1.5);
      w.setimag(5);
      cout << "El primer n’umero complejo es: " << z.getreal()
           << " + i*" << z.getimag() << endl;
      cout << "El segundo es: " << w.getreal() << " + i*"
           << z.getimag() << endl;
}

Vemos en la primera l´ınea de main c´mo la clase Complejo se usa del mismo
                                    o
modo que usar´ ıamos int o double. Ahora Complejo es un tipo de variable
tan v´lido como los tipos predefinidos por C++. Una vez definida la vari-
      a
able, el operador de selecci´n (.) permite acceder a las funciones p´blicas
                            o                                        u
correspondientes a la clase Complejo, aplicadas a la variable particular que
nos interesa: z.setreal(3) pone en la parte real del Complejo z el n´mero
                                                                      u
3, y w.setreal(1.5) hace lo propio con w.


                                    25
6.5    Implementaci´n de funciones miembros
                   o
Ya sabemos c´mo declarar funciones miembros en el interior de la clase y
             o
c´mo usarlas. Ahora veamos c´mo se implementan.
 o                          o

void Complejo::setreal(double x)
{
    real = x;
}

void Complejo::setimag(double x)
{
    imag = x;
}

double Complejo::getreal()
{
    return real;
}

double Complejo::getimag()
{
    return imaginaria;
}

Como toda funci´n, primero va el tipo de la funci´n (void o double en los
                  o                              o
ejemplos), luego el nombre de la funci´n y los argumentos. Finalmente la
                                      o
implementaci´n. Lo diferente es que el nombre va precedido del nombre de
               o
la clase y el operador “::” .

6.6    Constructor
Al declarar una variable, el programa crea el espacio de memoria suficiente
para alojarla. Cuando se trata de variables de tipos predefinidos en C++
esto no es problema, pero cuando son tipos definidos por el usuario C++
debe saber c´mo construir ese espacio. La funci´n que realiza esa tarea se
             o                                   o
denomina constructor.
    El constructor es una funci´n p´blica de la clase, que tiene el mismo
                                o   u
nombre que ella. Agreguemos un constructor a la clase Complejo:

                                   26
class Complejo
{
private:
    double real,imaginaria;
public:
    Complejo(double,double);
    void setreal(double);
    void setimag(double);
    double getreal();
    double getimag();
};

Complejo::Complejo (double x, double y): real(x), imaginaria(y)
{
}

Definir el constructor de esta manera nos permite crear en nuestro pro-
grama variables de tipo Complejo y asignarles valores sin usar setreal() o
setimag():

Complejo z (2, 3.8);
Complejo w = Complejo(6.8, -3);

    En el constructor se inicializan las variables internas que nos interesa
inicializar al momento de crear un objeto de esta clase.
    Si una de las variables internas a inicializar es una cadena de caracteres,
hay que inicializarla de modo un poco distinto. Por ejemplo, si estamos ha-
ciendo una clase Persona que s´lo tenga el nombre de una persona, entonces
                                 o
podemos definir la clase y su constructor en la forma:

class Persona
{
private:
    char nombre[20];
public:
    Persona(char []);
};




                                      27
Persona::Persona(a[])
{
   strcpy(nombre,a);
}

   Si uno no especifica el constructor de una clase C++ crea uno default,
pero en general ser´ insuficiente para cualquier aplicaci´n realmente pr´ctica.
                   a                                    o              a
Es una mala costumbre ser descuidado y dejar estas decisiones al computador.

6.7    Destructor
As´ como es necesario crear espacio de memoria al definir una variable,
  ı
hay que deshacerse de ese espacio cuando la variable deja de ser necesaria.
En otras palabras, la clase necesita tambi´n un destructor . Si la clase es
                                          e
Complejo, el destructor es una funci´n p´blica de ella, llamada ~Complejo.
                                    o u
class Complejo
{
private:
    double real, imaginaria;
public:
    Complejo(double,double);
    ~Complejo(void);
    void setreal(double);
    void setimag(double);
    double getreal();
    double getimag();
};

Complejo::Complejo (double x, double y): real(x), imaginaria(y)
{
}

Complejo::~Complejo(void)
{
}
   Como con los constructores, al omitir un destructor C++ genera uno
default, pero es una mala costumbre. . . , etc.

                                     28
6.8    Matrices de clases
Una clase es un tipo de variable como cualquier otro de los predefinidos en
C++. Es posible construir matrices con ellas, del mismo modo que uno
tiene matrices de enteros o caracteres. La unica diferencia con las matrices
                                           ´
usuales es que no se pueden s´lo declarar, sino que hay que inicializarlas
                               o
simult´neamente. Por ejemplo, si queremos crear una matriz que contenga
      a
2 n´meros complejos, la l´
   u                     ınea

Complejo z[2];

es incorrecta, pero s´ es aceptable la l´
                     ı                  ınea

Complejo z[2] = {Complejo(3.5,-0.8), Complejo(-2,4)};


7     Sobrecarga
Para que la definici´n de nuevos objetos sea realmente util, hay que ser ca-
                    o                                   ´
paz de hacer con ellos muchas acciones que nos ser´ naturales. Como ya
                                                    ıan
comentamos al introducir el concepto de clase, nos gustar´ sumar n´meros
                                                          ıa         u
complejos, y que esa suma utilizara el mismo signo + de la suma usual. O
extraerles la ra´ cuadrada, y que la operaci´n sea tan f´cil como escribir
                ız                             o          a
sqrt(z). Lo que estamos pidiendo es que el operador + o la funci´n sqrt()
                                                                  o
sean polim´rficos, es decir, que act´e de distinto modo seg´n el tipo de ar-
           o                        u                       u
gumento que se le entregue. Si z es un real, sqrt(z) calcular´ la ra´ de un
                                                              a     ız
n´mero real; si es complejo, calcular´ la ra´ de un n´mero complejo.
 u                                   a      ız       u
   La t´cnica de programaci´n mediante la cual podemos definir funciones
        e                    o
polim´rficas se llama sobrecarga.
     o

7.1    Sobrecarga de funciones
Digamos que la ra´ cuadrada de un n´mero complejo a + ib es (a/2) + i(b/2).
                  ız                u
(Es m´s complicado en realidad, pero no queremos escribir las f´rmulas
       a                                                          o
ahora.)
    Para sobrecargar la funci´n sqrt() de modo que acepte n´meros com-
                             o                               u
plejos basta definirla as´
                        ı:




                                       29
Complejo sqrt(Complejo z)
{
     return Complejo (z.getreal()/2, z.getimag()/2);
}
Observemos que definimos una funci´n sqrt que acepta argumentos de tipo
                                   o
Complejo, y que entrega un n´mero del mismo tipo. Cuando pidamos la ra´
                             u                                          ız
de un n´mero, el computador se preguntar´ si el n´mero en cuesti´n es un
        u                                 a        u              o
int, double, float o Complejo, y seg´n eso escoger´ la versi´n de sqrt que
                                     u              a       o
corresponda.
   Con la definici´n anterior podemos obtener la ra´ cuadrada de un n´mero
                 o                                ız                u
complejo simplemente con las instrucciones:
Complejo z(1,3);
Complejo raiz = sqrt(z);

7.2    Sobrecarga de operadores
¿C´mo le decimos al computador que el signo + tambi´n puede aceptar
   o                                                       e
n´meros complejos? La respuesta es f´cil, porque para C++ un operador
 u                                      a
no es sino una funci´n, y la acci´n de sobrecargar que ya vimos sirve en este
                    o            o
caso tambi´n. La sintaxis es:
           e
Complejo operator + (Complejo z, Complejo w)
{
    return Complejo (z.getreal() + w.getreal(),
                      z.getimag() + w.getimag());
}

7.3    Coerci´n
             o
Sabemos definir a + b, con a y b complejos. Pero ¿qu´ pasa si a o b son
                                                      e
enteros? ¿O reales? Pareciera que tendr´
                                       ıamos que definir no s´lo
                                                            o
Complejo operator + (Complejo a, Complejo b);
sino tambi´n todas las combinaciones restantes:
          e
Complejo operator + (Complejo a, int b);
Complejo operator + (Complejo a, float b);
Complejo operator + (int a, Complejo b);

                                     30
etc´tera.
   e
    En realidad esto no es necesario. Por cierto, un n´mero real es un n´mero
                                                      u                 u
complejo con parte imaginaria nula, y es posible hacerle saber esto a C++,
usando la posibilidad de definir funciones con par´metros default. Basta
                                                      a
declarar (en el interior de la clase) el constructor de los n´meros complejos
                                                             u
como
Complejo (double, double = 0);
Esto permite definir un n´mero complejo con la instrucci´n:
                        u                              o
Complejo c = Complejo(3.5);
resultando el n´mero complejo 3.5 + i · 0. Y si tenemos una l´
               u                                             ınea del tipo:
Complejo c = Complejo(3,2.8) + 5;
el computador convertir´ impl´
                        a     ıcitamente el entero 5 a Complejo (sabe como
hacerlo porque el constructor de n´meros complejos acepta tambi´n un solo
                                   u                             e
argumento en vez de dos), y luego realizar´ la suma entre dos complejos, que
                                          a
es entonces la unica que es necesario definir.
               ´


8    Punteros
Una de las ventajas de C++ es permitir el acceso directo del programador
a zonas de memoria, ya sea para crearlas, asignarles un valor o destruirlas.
Para ello, adem´s de los tipos de variables ya conocidos (int, double, clases),
                a
C++ proporciona un nuevo tipo: el puntero. El puntero no contiene el valor
de una variable, sino la direcci´n de memoria en la cual dicha variable se
                                 o
encuentra.
   Un peque˜o ejemplo nos permite ver la diferencia entre un puntero y la
              n
variable a la cual ese puntero “apunta”:
void main()
{
    int i = 42;
    int * p_i = &i;
    cout << "El valor del puntero es: " << p_i << endl;
    cout << "Y apunta a la variable: " << *p_i << endl;
}

                                      31
En este programa definimos una variable i entera, y luego un puntero a
esa variable, que en este caso denominamos p_i. Observemos la presencia
de los s´
        ımbolos * y &. Al ejecutar este programa, veremos en pantalla una
primera l´ınea que nos da el valor del puntero, donde encontraremos alg´n    u
n´mero hexadecimal imposible de determinar a priori, y que corresponde a
  u
la direcci´n de memoria donde qued´ ubicada la variable i. La segunda l´
          o                           o                                    ınea
nos da el valor de la variable que est´ en esa direcci´n de memoria: 42.
                                       a              o
    Los punteros tienen gran importancia cuando de manejar datos din´micos
                                                                         a
se trata, es decir, objetos que son creados durante la ejecuci´n del programa,
                                                              o
en n´mero imposible de predecir al momento de compilar. Por ejemplo, una
     u
aplicaci´n Windows normal que crea una, dos, tres, etc. ventanas a medida
        o
que uno abre archivos. En este caso, cada ventana es un objeto din´mico, a
creado durante la ejecuci´n, y la unica forma de manejarlo es a trav´s de un
                           o       ´                                   e
puntero a ese objeto.


9    Herencia
Herencia es el mecanismo mediante el cual es posible definir clases a partir
de otras, preservando parte de las propiedades de la primera y agregando o
modificando otras.
    Por ejemplo, si definimos la clase Persona, toda Persona tendr´ una
                                                                     a
variable miembro que sea su nombre. Si definimos una clase Hombre, tambi´ne
ser´ Persona, y por tanto deber´ tener nombre. Pero adem´s puede tener
   a                             ıa                         a
esposa. Y ciertamente no toda Persona tiene esposa. S´lo un Hombre.
                                                         o
    C++ provee mecanismos para implementar estas relaciones l´gicas y
                                                                   o
poder definir una clase Hombre a partir de Persona. Lo vemos en el siguiente
ejemplo:

class Persona
{
private:
    char nombre[20];
public:
    Persona(char [] = "");
    ~Persona(void);
    char getname();
}


                                      32
class Hombre : public Persona
{
private:
    char esposa[20];
public:
    Hombre(char a[]) : Persona(a)
    { };
    char getwife();
    void setwife();
}

    Primero definimos una clase Persona que tiene nombre. Luego definimos
una clase Hombre a partir de Persona (con la l´ınea class Hombre : public
Persona). Esto permite de modo autom´tico que Hombre tenga tambi´n una
                                          a                           e
variable nombre. Y finalmente, dentro de la clase Hombre, se definen todas
aquellas caracter´
                 ısticas adicionales que una Persona no tiene pero un Hombre
s´ esposa, y funciones miembros para modificar y obtener el nombre de ella.
 ı:
    Un ejemplo de uso de estas dos clases:

Persona cocinera("Maria");
Hombre panadero("Claudio");
panadero.setwife("Estela");

cout << cocinera.getname() << endl;
cout << panadero.getname() << endl;
cout << panadero.getwife() << endl;

    Observemos que panadero tambi´n tiene una funci´n getname(), a pe-
                                     e                 o
sar de que la clase Hombre no la define expl´ ıcitamente. Esta funci´n se ha
                                                                   o
heredado de la clase de la cual Hombre se ha derivado, Persona.




                                    33

Más contenido relacionado

La actualidad más candente

La actualidad más candente (15)

Algebra lineal
Algebra linealAlgebra lineal
Algebra lineal
 
Introduccion al lenguaje c
Introduccion al lenguaje cIntroduccion al lenguaje c
Introduccion al lenguaje c
 
Introduccion a la_programacion_con_c
Introduccion a la_programacion_con_cIntroduccion a la_programacion_con_c
Introduccion a la_programacion_con_c
 
Compiladores
CompiladoresCompiladores
Compiladores
 
Matematica ii derivadas e integrales
Matematica ii derivadas e integralesMatematica ii derivadas e integrales
Matematica ii derivadas e integrales
 
Apuntes de ecuaciones diferenciales
Apuntes de ecuaciones diferencialesApuntes de ecuaciones diferenciales
Apuntes de ecuaciones diferenciales
 
Manual Scilab
Manual ScilabManual Scilab
Manual Scilab
 
R manual
R manualR manual
R manual
 
Diseño canónico control automatico
Diseño canónico control automaticoDiseño canónico control automatico
Diseño canónico control automatico
 
Introduccion a matlab
Introduccion a matlabIntroduccion a matlab
Introduccion a matlab
 
Fractales.minimonograph
Fractales.minimonographFractales.minimonograph
Fractales.minimonograph
 
ANALISIS
ANALISISANALISIS
ANALISIS
 
M´etodos num´ericos
M´etodos num´ericosM´etodos num´ericos
M´etodos num´ericos
 
Curso de html y phpnuke
Curso de html y phpnukeCurso de html y phpnuke
Curso de html y phpnuke
 
Rarepaso
RarepasoRarepaso
Rarepaso
 

Destacado (9)

charla deodontogia cip puno
charla deodontogia cip punocharla deodontogia cip puno
charla deodontogia cip puno
 
Delphi
DelphiDelphi
Delphi
 
Megatendencias sociales
Megatendencias sociales Megatendencias sociales
Megatendencias sociales
 
Colegio de ingenieros 2016
Colegio de ingenieros 2016Colegio de ingenieros 2016
Colegio de ingenieros 2016
 
Metodo putnam - estimacion de costos y tiempo
Metodo putnam - estimacion de costos y tiempoMetodo putnam - estimacion de costos y tiempo
Metodo putnam - estimacion de costos y tiempo
 
marketing digital
marketing digitalmarketing digital
marketing digital
 
Cocomo II
Cocomo IICocomo II
Cocomo II
 
Exposicion de marketing UNA Puno
Exposicion de marketing UNA PunoExposicion de marketing UNA Puno
Exposicion de marketing UNA Puno
 
Materialismo dialéctico y materialismo histórico
Materialismo dialéctico y materialismo históricoMaterialismo dialéctico y materialismo histórico
Materialismo dialéctico y materialismo histórico
 

Similar a Manual cpp

ApuntesC++.pdf
ApuntesC++.pdfApuntesC++.pdf
ApuntesC++.pdfbilgrado01
 
Introducción a la programación en c
Introducción a la programación en cIntroducción a la programación en c
Introducción a la programación en cvictdiazm
 
43392462 analisis-matematico-ii-derivacion-de-funciones-de-varias-variables
43392462 analisis-matematico-ii-derivacion-de-funciones-de-varias-variables43392462 analisis-matematico-ii-derivacion-de-funciones-de-varias-variables
43392462 analisis-matematico-ii-derivacion-de-funciones-de-varias-variablesmarcopazo
 
Apuntes-MatematicasII
Apuntes-MatematicasIIApuntes-MatematicasII
Apuntes-MatematicasIImarvargas1981
 
52811100 manual-sp
52811100 manual-sp52811100 manual-sp
52811100 manual-sprnestor41
 
Libro programación-en-c++
Libro programación-en-c++Libro programación-en-c++
Libro programación-en-c++Andres Escobar
 
Calculo i, santiago relos
Calculo i, santiago relosCalculo i, santiago relos
Calculo i, santiago relos12miki
 
Funciones cuadráticas
Funciones cuadráticasFunciones cuadráticas
Funciones cuadráticasprofejmarisel
 
Matematicas en ingenieria_con_matlab_y_o
Matematicas en ingenieria_con_matlab_y_oMatematicas en ingenieria_con_matlab_y_o
Matematicas en ingenieria_con_matlab_y_oriberthancco
 
Teoria de la medida
Teoria de la medidaTeoria de la medida
Teoria de la medidajhorkham
 

Similar a Manual cpp (20)

Manualscilab 090513151714 Phpapp02
Manualscilab 090513151714 Phpapp02Manualscilab 090513151714 Phpapp02
Manualscilab 090513151714 Phpapp02
 
ApuntesC++.pdf
ApuntesC++.pdfApuntesC++.pdf
ApuntesC++.pdf
 
Vba excel mnumericos1
Vba excel mnumericos1Vba excel mnumericos1
Vba excel mnumericos1
 
Vba excel mnumericos
Vba excel mnumericosVba excel mnumericos
Vba excel mnumericos
 
Introducción al r
Introducción al rIntroducción al r
Introducción al r
 
Introducción a la programación en C
Introducción a la programación en CIntroducción a la programación en C
Introducción a la programación en C
 
Introducción a la programación en c
Introducción a la programación en cIntroducción a la programación en c
Introducción a la programación en c
 
43392462 analisis-matematico-ii-derivacion-de-funciones-de-varias-variables
43392462 analisis-matematico-ii-derivacion-de-funciones-de-varias-variables43392462 analisis-matematico-ii-derivacion-de-funciones-de-varias-variables
43392462 analisis-matematico-ii-derivacion-de-funciones-de-varias-variables
 
Manual de programacion lenguaje en C
Manual de programacion lenguaje en CManual de programacion lenguaje en C
Manual de programacion lenguaje en C
 
Apuntes-MatematicasII
Apuntes-MatematicasIIApuntes-MatematicasII
Apuntes-MatematicasII
 
52811100 manual-sp
52811100 manual-sp52811100 manual-sp
52811100 manual-sp
 
Libro programación-en-c++
Libro programación-en-c++Libro programación-en-c++
Libro programación-en-c++
 
Calculo diferencial
Calculo diferencialCalculo diferencial
Calculo diferencial
 
Calculo i, santiago relos
Calculo i, santiago relosCalculo i, santiago relos
Calculo i, santiago relos
 
Funciones cuadráticas
Funciones cuadráticasFunciones cuadráticas
Funciones cuadráticas
 
Libro cs1
Libro cs1Libro cs1
Libro cs1
 
Matematicas en ingenieria_con_matlab_y_o
Matematicas en ingenieria_con_matlab_y_oMatematicas en ingenieria_con_matlab_y_o
Matematicas en ingenieria_con_matlab_y_o
 
Introscilab
IntroscilabIntroscilab
Introscilab
 
Teoria de la medida
Teoria de la medidaTeoria de la medida
Teoria de la medida
 
Manual de c# 2
Manual de c# 2Manual de c# 2
Manual de c# 2
 

Más de Aldo Hernán Zanabria Gálvez

“PERSPECTIVAS DEL DESARROLLO ECONÓMICO REGIONAL EN EL CONTEXTO DEL CAMBIO CLI...
“PERSPECTIVAS DEL DESARROLLO ECONÓMICO REGIONAL EN EL CONTEXTO DEL CAMBIO CLI...“PERSPECTIVAS DEL DESARROLLO ECONÓMICO REGIONAL EN EL CONTEXTO DEL CAMBIO CLI...
“PERSPECTIVAS DEL DESARROLLO ECONÓMICO REGIONAL EN EL CONTEXTO DEL CAMBIO CLI...Aldo Hernán Zanabria Gálvez
 
Organizadores visuales sobre las corrientes contemporaneas aldo zanabria ga...
Organizadores visuales sobre las corrientes contemporaneas   aldo zanabria ga...Organizadores visuales sobre las corrientes contemporaneas   aldo zanabria ga...
Organizadores visuales sobre las corrientes contemporaneas aldo zanabria ga...Aldo Hernán Zanabria Gálvez
 
Resumen final - Seminario Taller TIC Emprede Turismo
Resumen final - Seminario Taller TIC Emprede TurismoResumen final - Seminario Taller TIC Emprede Turismo
Resumen final - Seminario Taller TIC Emprede TurismoAldo Hernán Zanabria Gálvez
 
Clase de Tecnologías de la Información y Comunicaciones
Clase de Tecnologías de la Información y ComunicacionesClase de Tecnologías de la Información y Comunicaciones
Clase de Tecnologías de la Información y ComunicacionesAldo Hernán Zanabria Gálvez
 

Más de Aldo Hernán Zanabria Gálvez (20)

“PERSPECTIVAS DEL DESARROLLO ECONÓMICO REGIONAL EN EL CONTEXTO DEL CAMBIO CLI...
“PERSPECTIVAS DEL DESARROLLO ECONÓMICO REGIONAL EN EL CONTEXTO DEL CAMBIO CLI...“PERSPECTIVAS DEL DESARROLLO ECONÓMICO REGIONAL EN EL CONTEXTO DEL CAMBIO CLI...
“PERSPECTIVAS DEL DESARROLLO ECONÓMICO REGIONAL EN EL CONTEXTO DEL CAMBIO CLI...
 
mejorando la web guia de html 5
mejorando la web guia de html 5mejorando la web guia de html 5
mejorando la web guia de html 5
 
Guía de Prácticas word beta.pdf
Guía de Prácticas word beta.pdfGuía de Prácticas word beta.pdf
Guía de Prácticas word beta.pdf
 
emprendimiento en la era del conocimiento.pptx
emprendimiento en la era del conocimiento.pptxemprendimiento en la era del conocimiento.pptx
emprendimiento en la era del conocimiento.pptx
 
Fundamentos de Programación
Fundamentos de ProgramaciónFundamentos de Programación
Fundamentos de Programación
 
Organizadores visuales sobre las corrientes contemporaneas aldo zanabria ga...
Organizadores visuales sobre las corrientes contemporaneas   aldo zanabria ga...Organizadores visuales sobre las corrientes contemporaneas   aldo zanabria ga...
Organizadores visuales sobre las corrientes contemporaneas aldo zanabria ga...
 
didactica
didacticadidactica
didactica
 
Tarea1 aldo zanabria
Tarea1 aldo zanabriaTarea1 aldo zanabria
Tarea1 aldo zanabria
 
Tarea 2 aldo zanabria
Tarea 2 aldo zanabriaTarea 2 aldo zanabria
Tarea 2 aldo zanabria
 
Carolinos del milenio pasado - Puno
Carolinos del milenio pasado - PunoCarolinos del milenio pasado - Puno
Carolinos del milenio pasado - Puno
 
ingenieria de sistemas
ingenieria de sistemasingenieria de sistemas
ingenieria de sistemas
 
Electricidad con recursos renovables
Electricidad con recursos renovablesElectricidad con recursos renovables
Electricidad con recursos renovables
 
Variables
VariablesVariables
Variables
 
Estructura y modelo organizacional estatal
Estructura y modelo organizacional estatal Estructura y modelo organizacional estatal
Estructura y modelo organizacional estatal
 
Calidad de Agua
Calidad de AguaCalidad de Agua
Calidad de Agua
 
Resumen final - Seminario Taller TIC Emprede Turismo
Resumen final - Seminario Taller TIC Emprede TurismoResumen final - Seminario Taller TIC Emprede Turismo
Resumen final - Seminario Taller TIC Emprede Turismo
 
Clase de Tecnologías de la Información y Comunicaciones
Clase de Tecnologías de la Información y ComunicacionesClase de Tecnologías de la Información y Comunicaciones
Clase de Tecnologías de la Información y Comunicaciones
 
Plan de Trabajo Integración de la Mujer
Plan de Trabajo Integración de la MujerPlan de Trabajo Integración de la Mujer
Plan de Trabajo Integración de la Mujer
 
peritaciones y tasación puno
peritaciones y tasación punoperitaciones y tasación puno
peritaciones y tasación puno
 
producción en la empresa turística
producción en la empresa turísticaproducción en la empresa turística
producción en la empresa turística
 

Manual cpp

  • 1. Una breve introducci´n a C++ o V´ ıctor Mu˜oz n Contenidos 1 Introducci´n o 3 2 Estructura b´sica de un programa a en C++ 3 2.1 El programa m´s simple . . . . . a . . . . . . . . . . . . . . . . 3 2.2 Definici´n de funciones . . . . . . o . . . . . . . . . . . . . . . . 4 2.3 Nombres de variables . . . . . . . . . . . . . . . . . . . . . . . 4 2.4 Tipos de variables . . . . . . . . . . . . . . . . . . . . . . . . . 4 2.5 Ingreso de datos desde el teclado . . . . . . . . . . . . . . . . 6 2.6 Operadores aritm´ticos . . . . . . e . . . . . . . . . . . . . . . . 6 2.7 Operadores relacionales . . . . . . . . . . . . . . . . . . . . . . 7 2.8 Asignaciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 2.9 Conversi´n de tipos . . . . . . . . o . . . . . . . . . . . . . . . . 8 3 Control de flujo 9 3.1 if, if... else, if... else if . . . . . . . . . . . . . . . 9 3.2 Expresi´n condicional . . o . . . . . . . . . . . . . . . . . . . . . 10 3.3 switch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 3.4 while . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 3.5 for . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 3.6 do... while . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 3.7 goto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 4 Funciones 12 4.1 Funciones tipo void . . . . . . . . . . . . . . . . . . . . . . . 12 4.2 return . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 4.3 Funciones con par´metros a . . . . . . . . . . . . . . . . . . . . 13 4.4 Par´metros default . . . . a . . . . . . . . . . . . . . . . . . . . 15 1
  • 2. 4.5 Alcance, visibilidad, tiempo de vida . . . . . . . . . . . . . . . 16 4.6 Recursi´n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 o 5 Matrices 17 5.1 Declaraci´n e inicializaci´n . . . . . . . . o o . . . . . . . . . . . . 17 5.2 Matrices como par´metros de funciones . a . . . . . . . . . . . . 18 5.3 Matrices multidimensionales . . . . . . . . . . . . . . . . . . . 19 5.4 Matrices de caracteres: cadenas (strings) . . . . . . . . . . . . 19 5.4.1 string.h . . . . . . . . . . . . . . . . . . . . . . . . . . 20 5.4.2 Input/Output de cadenas . . . . . . . . . . . . . . . . 20 6 Clases 21 6.1 Definici´n . . . . . . . . . . . . . . . . o . . . . . . . . . . . . . 23 6.2 Miembros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 6.3 Miembros p´blicos y privados . . . . . u . . . . . . . . . . . . . 24 6.4 Operador de selecci´n (.) . . . . . . . . o . . . . . . . . . . . . . 25 6.5 Implementaci´n de funciones miembros o . . . . . . . . . . . . . 26 6.6 Constructor . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 6.7 Destructor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 6.8 Matrices de clases . . . . . . . . . . . . . . . . . . . . . . . . . 29 7 Sobrecarga 29 7.1 Sobrecarga de funciones . . . . . . . . . . . . . . . . . . . . . 29 7.2 Sobrecarga de operadores . . . . . . . . . . . . . . . . . . . . . 30 7.3 Coerci´n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 o 8 Punteros 31 9 Herencia 32 2
  • 3. 1 Introducci´n o Estos apuntes corresponden a un peque˜o intento de ordenar los temas n abordados en el curso de Computaci´n para Matem´ticos dictado el Primer o a Semestre de 1998. No pretendo que sean tomados muy en serio, en el sen- tido que est´n dise˜ados para satisfacer las m´ a n ınimas necesidades del curso, sirviendo como un ayuda-memoria de los t´picos abordados, para futura o referencia. No se consideran todas las posibilidades del lenguaje, y las ex- plicaciones est´n reducidas al m´ a ınimo o est´n ausentes del todo, de modo a que creo son m´s utiles para quienes ya sepan algo de C++ (idealmente los a ´ alumnos del curso una vez terminado ´ste) y quieran recordar alg´n detalle e u de sintaxis ya olvidado. Tambi´n pueden servir para personas con alguna e experiencia en otros lenguajes de programaci´n y que deseen comenzar el o aprendizaje de C++. El mundo est´ lleno de manuales a los cuales se puede a acudir en caso de urgencias m´s elevadas. S´lo el Tiempo y mi tiempo dir´n a o a si estos apuntes ser´n extendidos alguna vez. a 2 Estructura b´sica de un programa en C++ a 2.1 El programa m´s simple a El primer ejemplo de todo manual es el que permite escribir “Hola” en la pantalla del computador. #include <iostream.h> void main() { cout << "Hola." << endl; } La primera l´ ınea define las instrucciones adecuadas para enviar luego un mensaje a pantalla. La funci´n main es donde comienza a ejecutarse el o programa; siempre debe haber una funci´n main en nuestro programa. cout o env´ el mensaje a pantalla, y endl agrega un cambio de l´ ıa ınea al final del mensaje. 3
  • 4. 2.2 Definici´n de funciones o Uno puede delegar la impresi´n del mensaje anterior a una funci´n indepen- o o diente: #include <iostream.h> void PrintHola() { cout << "Hola." << endl; } void main() { PrintHola(); } 2.3 Nombres de variables – Deben comenzar con una letra (may´sculas y min´sculas son distintas). u u – Pueden contener n´meros. u – Pueden contener el s´ ımbolo _ (underscore). – Longitud arbitraria. – No pueden corresponder a una de las 48 palabras reservadas de C++ (if, else, etc.). 2.4 Tipos de variables Todas las variables a usar deben ser declaradas de acuerdo a su tipo. Por ejemplo, si usamos una variable i que sea un n´mero entero, debemos, antes u de usarla, declararla, y s´lo entonces podemos asignarle un valor: o int i; i=10; 4
  • 5. Es posible reunir las acciones de declaraci´n e inicializaci´n en una misma o o l´ ınea: int i = 10; Los tipos de variables disponibles son1 : int Enteros entre −215 = −32768 y 215 − 1 = 32767 o entre −231 = −2147483648 y 231 − 1 = 2147483647 short int short Enteros entre −215 y 215 − 1. long int long Enteros entre −231 y 231 − 1. unsigned int Enteros entre 0 y 216 − 1 o entre 0 y 232 − 1. unsigned short Enteros entre 0 y 216 − 1. unsigned long Enteros entre 0 y 232 − 1. char Caracteres. float Reales en los intervalos [−1.7 · 1038 , −0.29 · 10−38 ], [0.29 · 10−38 , 1.7 · 1038 ] (Precisi´n de unos 7 d´ o ıgitos decimales.) double Reales en los mismos intervalos que float, pero con precisi´n de 16 decimales, o o en los intervalos [−0.9 · 10308 , −0.86 · 10−308 ] y [0.86 · 10−308 , 0.9 · 10308 ], con precisi´n de o 15 decimales. Las variables tipo char alojan caracteres, debiendo inicializarse en la forma: char c = ’a’; Adem´s de las letras may´sculas y min´sculas, y s´ a u u ımbolos como &, (, :, etc., hay una serie de caracteres especiales (caracteres de escape) que es posible asignar a una variable char. Ellos son: 1 Los valores de los rangos indicados son simplemente representativos y dependen de la m´quina utilizada. a 5
  • 6. newline n horizontal tab t vertical tab v backspace b carriage return r form feed f alert (bell) a backslash single quote ’ double quote " Por ejemplo, la l´ ınea: cout << "Primera columnat Segunda columnan Segunda linea" << endl; corresponde al output Primera columna Segunda columna Segunda linea 2.5 Ingreso de datos desde el teclado #include <iostream.h> void main() { int i; cout << "Ingrese un numero entero: "; cin >> i; cout << "El numero ingresado fue: " << i << endl; } 2.6 Operadores aritm´ticos e Existen operadores para la suma, la resta, la multiplicaci´n, la divisi´n: o o + - * / 6
  • 7. 2.7 Operadores relacionales Los s´ımbolos para las relaciones de igualdad, desigualdad, menor, menor o igual, mayor y mayor o igual son: == != < <= > >= Para las relaciones l´gicas AND, OR y NOT: o && || ! 2.8 Asignaciones a) Asignaci´n simple. o i = 1; b) Asignaci´n compuesta. o La expresi´n o x = x + 2 se puede reemplazar por x += 2 Existen los operadores += -= *= /= c) Operadores de incremento y decremento. La expresi´n o x = x + 1 se puede reescribir x += 1 o bien x++ An´logamente, existe el operador --. a 7
  • 8. 2.9 Conversi´n de tipos o Observemos que en una expresi´n del tipo: o int i = 3; float x = 43.8; cout << "Suma = " << x + i << endl; el computador debe sumar dos variables de tipos distintos, y por tanto debe convertir ambas a un tipo com´n antes de efectuar la suma. Existen dos u modos de proceder: a) Conversi´n expl´ o ıcita. Insertar la expresi´n o j = float(i); Esto es bastante tedioso, por cuanto el programador debe realizar el trabajo de conversi´n personalmente. o b) Conversi´n impl´ o ıcita. El compilador realiza las conversiones de modo autom´tico, prefiriendo a siempre la conversi´n desde un tipo de variable de menor precisi´n a o o uno de mayor precisi´n (de int a double, de short a int, etc.). o Es interesante notar c´mo las conversiones impl´ o ıcitas de tipos pueden tener consecuencias insospechadas y esot´ricas. e Consideremos las tres expresiones: i) x = (1/2) * (x + a/x) ; ii) x = (0.5) * (x + a/x) ; iii) x = (x + a/x)/2 ; Si inicialmente x=0.5 y a=0.5, por ejemplo, i) entrega el valor x=0, mientras ii) y iii) entregan el valor x=1.5. Lo que ocurre es que 1 y 2 son enteros, de modo que 1/2 = 0. De acuerdo a lo que dijimos, uno esperar´ que en i), como conviven n´meros reales con enteros, los ıa u n´meros enteros fueran convertidos a reales y, por tanto, la expresi´n u o tuviera el resultado esperado, 1.5. El problema es la prioridad de las 8
  • 9. operaciones. No todas las operaciones tienen igual prioridad (las mul- tiplicaciones y divisiones se realizan antes que las sumas y restas, por ejemplo), y esto permite al compilador decidir cu´l operaci´n efectuar a o primero. Cuando se encuentra con operaciones de igual prioridad (dos multiplicaciones, por ejemplo), se procede a efectuarlas de izquierda a derecha. Pues bien, en i), la primera operaci´n es 1/2, una divisi´n entre en- o o teros, i.e. cero. En ii) no hay problema, porque todas son operaciones entre reales. Y en iii) la primera operaci´n es el par´ntesis, que es una o e operaci´n entre reales. Al dividir por 2 ´ste es convertido a real antes o e de calcular el resultado. i) a´n podr´ utilizarse, cambiando el prefactor del par´ntesis a 1.0/2.0, u ıa e una pr´ctica que ser´ conveniente adoptar como standard cuando quer- a ıa emos utilizar enteros dentro de expresiones reales, para evitar errores que pueden llegar a ser muy oscuros. 3 Control de flujo 3.1 if, if... else, if... else if a) if (a==b) { cout << "a es igual a b" << endl; } b) if (c!=d) { cout << "c es distinto de d" << endl; } else { cout << "c es igual a d" << endl; } c) if (e > f) { cout << "e es mayor que f" << endl; 9
  • 10. } else if (e == f) { cout << "e es igual a f" << endl; } else { cout << "e es menor que f" << endl; } 3.2 Expresi´n condicional o if (a==b) { c = 1; } else { c = 0; } se puede reemplazar por c = (a==b) ? 1 : 0; 3.3 switch switch (i) { case 1: { cout << "Caso 1." << endl; } break; case 2: { cout << "Caso 2." << endl; } 10
  • 11. break; default: { cout << "Otro caso." << endl; } break; } La instrucci´n break permite que la ejecuci´n del programa salte a la o o l´ ınea siguiente despu´s de la serie de instrucciones asociadas a switch. Por e ejemplo, si no existieran los break, e i=1, entonces ver´ ıamos en pantalla las l´ ıneas Caso 1., Caso 2. y Otro caso. La instrucci´n default es opcional. o 3.4 while while (i < 3) { cout << i << endl; i++; } 3.5 for for (i = 1; i < 10; i++) { cout << "Valor del indice: " << i << endl; } Los argumentos segundo y tercero de for son opcionales (no los ;). Adem´s, se puede involucrar m´s de una variable en el ciclo: a a for (i=0, k=20; (i<10) && (k<100); i++, k+=6) { cout << "i + k = " << i + k << endl; } 11
  • 12. 3.6 do... while do { cout << i << endl; i++; } while (i<=20); 3.7 goto Existe tambi´n en C++ una instrucci´n goto que permite saltar de un punto e o a otro del programa (goto salto; permite saltar a la l´ ınea que contiene la instrucci´n salto:). Sin embargo, se considera una mala t´cnica de pro- o e gramaci´n usar goto, y siempre se puede dise˜ar un programa evit´ndolo. o n a Altamente no recomendable. 4 Funciones Las funciones nos permiten programar partes del procedimiento por separado. Un ejemplo simple de ellas lo vimos en la subsecci´n 2.2. o 4.1 Funciones tipo void Un caso especial de funciones es aqu´l en que el programa que llama la funci´n e o no espera que ´sta le entregue ning´n valor al terminar. Por ejemplo, en la e u subsecci´n 2.2, la funci´n PrintHola simplemente imprime un mensaje en o o pantalla. El resto del programa no necesita de ning´n resultado parcial u proveniente de la ejecuci´n de dicha funci´n. La definici´n de estas funciones o o o debe ir precedida de la palabra void, como en el ejemplo citado. Observemos que la funci´n main en todos nuestros ejemplos hasta ahora es una funci´n o o de tipo void tambi´n. e 4.2 return Si deseamos definir una funci´n que calcule una ra´ cuadrada, evidente- o ız mente esperamos que la funci´n nos entregue un resultado: el valor de la ra´ o ız 12
  • 13. cuadrada. En este caso hay que traspasar el valor de una variable desde la funci´n al programa que la llam´. Esto se consigue con return. o o int numero() { int i = 3; return i; } void main() { cout << "Llamamos a la funcion" << endl; cout << "El numero es: " << numero() << endl; int i = 5; i = i + numero(); cout << "El numero mas 5 es: " << i << endl; } En este caso, la funci´n simplemente entrega el valor de la variable interna o i, es decir 3, el cual puede ser usado para salida en pantalla o dentro de operaciones matem´ticas corrientes. a Dos observaciones utiles: ´ a) La declaraci´n de la funci´n lleva antepuesto el tipo de variable que o o la funci´n entrega. En el ejemplo, la variable entregada es un entero, o i, y la declaraci´n debe ser por tanto: int numero(). Podemos tener o funciones tipo double, char, long, etc., de acuerdo al tipo de variable que corresponde a return. b) La variable i que se usa dentro de main() y la que se usa dentro de numero() son distintas. A pesar de que tienen el mismo nombre, se pueden usar independientemente como si se llamaran distinto. Se dice que i es una variable local. 4.3 Funciones con par´metros a Volviendo al ejemplo de la ra´ cuadrada, nos gustar´ llamar a esta funci´n ız ıa o con un par´metro (el n´mero al cual se le va a calcular la ra´ cuadrada). a u ız Existen dos modos de transferir par´metros a una funci´n: a o 13
  • 14. a) Por valor. int funcion(int i) { i+=4; return i; } void main() { i = 3; cout << "El valor de la funcion es " << funcion(i) << endl; cout << "El valor del parametro es " << i << endl; } El resultado en pantalla es: El valor de la funcion es 7 El valor del parametro es 3 La funci´n funcion entrega el valor del par´metro m´s 4. Usamos o a a el mismo nombre (i) para las variables en main y funcion, pero son variables locales, as´ que no interfieren. Lo importante es notar que ı cuando se llama la funci´n, la reasignaci´n del valor de i [i+=4] ocurre o o s´lo para la variable local en funcion; el par´metro externo mantiene o a su valor. Lo que ha ocurrido es que la funci´n copia el valor de la variable externa o i en una nueva variable (que tambi´n se llama i, pero est´ en otra e a direcci´n de memoria). El valor con el que trabaja la funci´n es la o o copia, manteniendo inalterada la variable original. b) Por referencia. int funcion(int & i) { i+=4; 14
  • 15. return i; } void main() { i = 3; cout << "El valor de la funcion es " << funcion(i) << endl; cout << "El valor del parametro es " << i << endl; } ´ Este es el mismo ejemplo anterior, pero modificando la declaraci´n del o argumento en funcion. El efecto es que en vez de traspasarle a funcion el valor del par´metro, se le entrega la direcci´n de memoria de dicha a o variable, permiti´ndosele de este modo modificar su valor. El resultado e en pantalla del ultimo programa ser´: ´ a El valor de la funcion es 7 El valor del parametro es 7 El paso de par´metros por referencia debe ser usado con sabidur´ a ıa. De hecho el ejemplo presentado es poco recomendable. Un caso m´s a util es el intercambiar entre s´ el valor de dos variables, digamos a1=1 ´ ı y a2=3. Luego de ejecutar la funci´n queremos que a1=3 y a1=1, es o decir, precisamente que el valor de las variables originales cambie. El uso de par´metros por referencia es la t´cnica a usar en esta situaci´n. a e o 4.4 Par´metros default a C++ permite que omitamos algunos par´metros de la funci´n llamada, la a o cual reemplaza los valores omitidos por otros predeterminados. Tomemos por ejemplo la funci´n de la subsecci´n 4.3, y modifiqu´mosla de modo que o o e si no le entregamos par´metros, asuma que el n´mero entregado fue 5: a u int funcion(int i = 5) { i+=4; 15
  • 16. return i; } void main() { cout << "El resultado default es " << funcion() << endl; int i = 3; cout << "Cuando el parametro vale " << i << " el resultado es " << funcion(i) << endl; } El output correspondiente es: El resultado default es 9 Cuando el parametro vale 3 el resultado es 7 4.5 Alcance, visibilidad, tiempo de vida Con el concepto de funci´n hemos apreciado que es posible que coexistan o variables con el mismo nombre en puntos distintos del programa, y que sig- nifiquen cosas distintas. Conviene entonces tener en claro tres conceptos que est´n ligados a esta propiedad: a Alcance La secci´n del c´digo durante la cual el nombre de una variable o o puede ser usado. Comprende desde la declaraci´n de la variable hasta o el final del cuerpo de la funci´n donde es declarada. o Si la variable es declarada dentro de una funci´n es local . Si es definida o fuera de todas las funciones (incluso fuera de main), la variable es global. Visibilidad Indica cu´les de las variables actualmente al alcance pueden ser a accesadas. En nuestros ejemplos (subsecci´n 4.3), la variable i en main o a´n est´ al alcance dentro de la funci´n funcion, pero no es visible, y u a o por eso es posible reutilizar el nombre. Tiempo de vida Indica cu´ndo las variables son creadas y cu´ndo destru- a a idas. En general este concepto coincide con el alcance (las variables son creadas cuando son declaradas y destruidas cuando la funci´n dentro de o la cual fueron declaradas termina), salvo porque es posible definir: (a) variables din´micas, que no tienen alcance, sino s´lo tiempo de vida; a o 16
  • 17. (b) variables est´ticas, que conservan su valor entre llamadas sucesivas a de una funci´n (estas variables tienen tiempo de vida mayor que su o alcance). 4.6 Recursi´n o C++ soporta un tipo especial de t´cnica de programaci´n, la recursi´n, que e o o permite que una funci´n se llame a s´ misma. Esto permite definir de modo o ı muy compacto una funci´n que calcule el factorial de un n´mero entero n. o u int factorial(int n) { return (n<2) ? 1: n * factorial(n-1); } 5 Matrices 5.1 Declaraci´n e inicializaci´n o o Podemos declarar (e inicializar inmediatamente) matrices de enteros, reales de doble precisi´n, caracteres, etc., seg´n nuestras necesidades. o u int a[5]; double r[3] = {3.5, 4.1, -10.8}; char palabra[5]; Una vez declarada la matriz (digamos a[5]), los valores individuales se accesan con a[i], con i desde 0 a 4. Por ejemplo, podemos inicializar los elementos de la matriz as´ ı: a[0] = 3; a[3] = 5; ... o si queremos ingresarlos desde el teclado: for (i = 0; i < 5; i++) { cin >> a[i]; } 17
  • 18. Y si deseamos escribirlos en pantalla: for (i = 0; i < 5; i++) { cout >> a[i]; } 5.2 Matrices como par´metros de funciones a Si deseamos, por ejemplo, dise˜ar una funci´n que mande los elementos de n o una matriz a pantalla: void PrintMatriz(int i, double a[]) { for (int j = 0; j < i; j++) { cout << "Elemento " << j << " = " << a[j] << endl; } } void main() { double matriz[5] = {3.5, 5.2, 2.4, -0.9, -10.8}; PrintMatriz(5, matriz); } Observemos que la funci´n debe recibir dos par´metros, uno de los cuales o a es la dimensi´n de la matriz. Esto se debe a que cuando las matrices son o usadas como par´metros la informaci´n de su dimensi´n no es traspasada, a o o y debe ser comunicada independientemente. Una ligera optimizaci´n al pro- o grama anterior es modificar main a: void main() { int dim = 5; double matriz[dim] = {3.5, 5.2, 2.4, -0.9, -10.8}; PrintMatriz(dim, matriz); } 18
  • 19. De este modo, si eventualmente cambiamos de opini´n y deseamos trabajar o con matrices de longitud distinta, s´lo hay que modificar una l´ o ınea de c´digo o (la primera) en todo el programa, el cual puede llegar a ser bastante largo por cierto. (En el ejemplo, tambi´n habr´ que cambiar la l´ e ıa ınea de inicial- izaci´n de la matriz, porque asume que la matriz requiere s´lo 5 elementos, o o pero de todos modos deber´ ser clara la enorme conveniencia —en progra- ıa mas m´s generales— de definir la dimensi´n de la matriz como una variable a o independiente.) 5.3 Matrices multidimensionales Es f´cil declarar e inicializar matrices de m´s de una dimensi´n: a a o double array[10][8]; int array[2][3] = {{1, 2, 3}, {4, 5, 6}}; 5.4 Matrices de caracteres: cadenas (strings) Una cadena es una matriz de caracteres que termina con el char nulo: ’0’. char palabra[5] = {’H’, ’o’, ’l’, ’a’, ’0’}; Cuando enviamos esta matriz a pantalla: for (i = 0; i < 5; i++) { cout << palabra[i]; } El resultado es Hola. Es equivalente esto a la instrucci´n ya conocida o cout << "Hola". De hecho, la declaraci´n de palabra podr´ haberse es- o ıa crito: char palabra[5] = "Hola"; Las l´ ıneas de texto, entonces, no corresponden sino a matrices de car- acteres. Se entiende entonces la necesidad de introducir el char especial ’0’. En efecto, toda matriz en C++ debe tener una dimensi´n definida. o Sin embargo, las palabras o las l´ ıneas de texto que se nos pudiera ocurrir uti- lizar pueden tener una longitud arbitraria, lo cual genera un conflicto. C++ resuelve el problema aceptando que estas matrices de caracteres tengan lon- gitud arbitraria, pero adoptando la convenci´n de se˜alar d´nde terminan. o n o 19
  • 20. 5.4.1 string.h Una serie de funciones utiles para manejar palabras (convertir todas las letras ´ en may´sculas, contar el n´mero de caracteres, etc.) son accesibles agregando u u al comienzo del programa la l´ ınea: #include <string.h> Por ejemplo: a) strlen(a) entrega el n´mero de caracteres de la cadena a (como un u humano lo entender´ es decir, sin incluir ’0’). ıa, b) strncpy(a,b) copia la cadena b en a. (Podr´ ıamos esperar que, como cuando intervienen variables num´ricas, esto se realizara con a=b, pero e no es as´ ı.) 5.4.2 Input/Output de cadenas Ya sabemos que la salida a pantalla de cadenas se realiza con cout y << simplemente, como con todos los dem´s tipos de variables. a El ingreso por teclado de cadenas es m´s problem´tico debido a la longitud a a indeterminada de la matriz. La soluci´n m´s f´cil es: o a a char a[30]; cout << "Ingrese una palabra: "; cin >> a; La idea es que la matriz sea suficientemente grande (30 caracteres en este caso) para que una palabra cualquiera quepa holgadamente. Las dificultades que aparecen son dos: a) La longitud del input puede ser demasiado grande. El problema de esto es que un input demasiado grande aloja caracteres en direcciones de memoria sobre los cuales no se tiene ningun control, con consecuencias posiblemente catastr´ficas en aplicaciones suficientemente complicadas. o La soluci´n ser´ aumentar el tama˜o de la matriz (lo cual no se puede o ıa n hacer hasta infinito en todo caso). b) S´lo se puede ingresar una palabra a la vez. Esto es porque C++ con- o sidera a los espacios en blanco como fin de input. Esto no es necesari- amente una desventaja, porque si queremos ingresar por teclado varios 20
  • 21. valores de una sola vez, basta separarlos por espacios. Pero cuando se trata de texto no necesariamente queremos ingresar palabras individ- uales. Una soluci´n al problema b) es ingresar l´ o ıneas completas (i.e. hasta que aparezca un ’n’ o Enter). Claro que esto no soluciona el problema del control de la longitud del texto (una l´ ınea podr´ ser m´s larga que cualquier ıa a longitud preconcebida), problema que debe ser tratado por separado. El siguiente programa muestra un ejemplo de soluci´n para ambas situa- o ciones: int buffersize = 512; char inputBuffer[buffersize]; if (cin.getline(inputBuffer,buffersize-1)) { cout << inputBuffer << endl; } else { cout << "Demasiado larga: " << inputBuffer << endl; while (cin.clear(), !cin.getline(inputBuffer, buffersize-1)) { cout << " y tambien: " << inputBuffer << endl; } cout << " y finalmente: " << inputBuffer << endl; } En este programa, cin.getline(inputBuffer,buffersize) recibe una l´ ınea desde el teclado hasta que encuentra un fin de l´ ınea, con un m´ximo a de buffersize-1 caracteres, a˜adiendo al final un ’0’. Esta funci´n es n o falsa si algo sali´ mal en el proceso de ingreso de datos (por ejemplo, si se o ingresaron m´s caracteres que la longitud establecida). a cin.clear() resetea el estado del mecanismo de input, prepar´ndolo para a una nueva sesi´n de ingreso. o 6 Clases C++ dispone de una serie de tipos de variables con los cuales nos est´ per- a mitido operar: int, double, char, etc. Creamos variables de estos tipos y 21
  • 22. luego podemos operar con ellos: int x, y; x = 3; y = 6; int z = x + y; No hay, sin embargo, en C++, una estructura predefinida que corre- sponda a n´meros complejos, vectores de dimensi´n n o matrices, por ejem- u o plo. Y sin embargo, nos agradar´ disponer de n´meros complejos que ıa u pudi´ramos definir como e z = (3,5); w = (6,8); y que tuvieran sentido las expresiones a = z + w; b = z * w; c = z / w; d = z + 3; e = modulo(z); f = sqrt(z); Todas estas expresiones son completamente naturales desde el punto de vista matem´tico, y ser´ bueno que el lenguaje las entendiera. Esto es a ıa imposible en el estado actual, pues, por ejemplo, el signo + es un operador que espera a ambos lados suyos un n´mero. Sumar cualquier cosa con cualquier u cosa no significa nada necesariamente, as´ que s´lo est´ permitido operar ı o a con n´meros. Pero los humanos sabemos que los complejos son n´meros. u u ¿C´mo dec´ o ırselo al computador? ¿C´mo convencerlo de que sumar vectores o o matrices es tambi´n posible matem´ticamente, y que el mismo signo + e a deber´ servir para todas estas operaciones? ıa La respuesta es: a trav´s del concepto de clases. Lo que debemos hacer e es definir una clase de n´meros complejos. Llam´mosla Complejo. Una u e vez definida correctamente, Complejo ser´ un tipo m´s de variable que el a a compilador reconocer´, igual que int, double, char, etc. Y ser´ tan f´cil a a a operar con los Complejos como con todos los tipos de variables preexistentes. Esta facilidad es la base de la extensibilidad de que es capaz C++, y por tanto de todas las propiedades que lo convierten en un lenguaje muy poderoso. 22
  • 23. Las clases responden a la necesidad del programador de construir objetos o tipos de datos que respondan a sus necesidades. Si necesitamos trabajar con vectores de 5 coordenadas, ser´ natural definir una clase que corresponda a a vectores con 5 coordenadas; si se trata de un programa de administraci´n de o personal, la clase puede corresponder a un empleado, con sus datos personales como elementos. Si bien es cierto uno puede trabajar con clases en el contexto de ori- entaci´n al procedimiento, las clases muestran con mayor propiedad su po- o tencial con la orientaci´n al objeto, donde cada objeto corresponde a una o clase. Por ejemplo, para efectuar una aplicaci´n para Windows, la ventana o principal, las ventanas de los archivos abiertos, la barra de men´, las cajas u de di´logo, los botones, etc., cada uno de estos objetos estar´ asociado a una a a clase. 6.1 Definici´n o Digamos que queremos una clase para representar los empleados de una em- presa. Llam´mosla Persona. La convenci´n aceptada es que los nombres de e o las clases comiencen con may´scula. Esto es porque las clases, recordemos, u corresponder´n a tipos de variables tan v´lidos como los internos de C++ a a (int, char, etc.). Al usar nombres con may´scula distiguimos visualmente u los nombres de un tipo de variable interno y uno definido por el usuario. La estructura m´ ınima de la definici´n de la clase Persona es: o class Persona { }; Todas las caracter´ ısticas de la clase se definen entre los parent´sis cursivos. e 6.2 Miembros Se denomina miembros de una clase a todas las variables y funciones declaradas dentro de una clase. Por ejemplo, para personas, es natural caracterizarlas por su nombre y su edad. Y si se trata de empleados de una empresa, es natural tambi´n tener una funci´n que entregue su sueldo: e o 23
  • 24. class Persona { char nombre[20]; int edad; double sueldo(); } Los miembros de una funci´n pueden tener cualquier nombre, excepto el o nombre de la propia clase dentro de la cual se definen. 6.3 Miembros p´ blicos y privados u Una clase distingue informaci´n (datos o funciones) privada (accesible s´lo a o o otros miembros de la misma clase) y p´blica (accesible a funciones externas u a la clase). La parte privada corresponde a la estructura interna de la clase, y la parte p´blica a la implementaci´n (t´ u o ıpicamente funciones), que permite la interacci´n de la clase con el exterior. o Consideremos ahora nuestro deseo de tener una clase que represente n´meros complejos. Un n´mero complejo tiene dos n´meros reales (parte u u u real e imaginaria), y ´sos son elementos privados —es decir, parte de su es- e tructura interna. Sin embargo, nos gustar´ poder modificar y conocer esas ıa cantidades. Eso s´lo puede hacerse a trav´s de funciones p´blicas. o e u class Complejo { private: double real, imaginaria; public: void setreal(double); void setimag(double); double getreal(); double getimag(); }; En este ejemplo, los miembros privados son s´lo variables, y los miembros o u o ´ p´blicos son s´lo funciones. Este es el caso t´ ıpico, pero puede haber variables y funciones de ambos tipos. 24
  • 25. 6.4 Operador de selecci´n (.) o Hemos definido una clase de n´meros complejos y funciones que nos per- u miten conocer y modificar las partes real e imaginaria. ¿C´mo se usan estos o elementos? Consideremos el siguiente programa de ejemplo: class Complejo { private: double real, imaginaria; public: void setreal(double); void setimag(double); double getreal(); double getimag(); }; void main() { Complejo z, w; z.setreal(3); z.setimag(2.8); w.setreal(1.5); w.setimag(5); cout << "El primer n’umero complejo es: " << z.getreal() << " + i*" << z.getimag() << endl; cout << "El segundo es: " << w.getreal() << " + i*" << z.getimag() << endl; } Vemos en la primera l´ınea de main c´mo la clase Complejo se usa del mismo o modo que usar´ ıamos int o double. Ahora Complejo es un tipo de variable tan v´lido como los tipos predefinidos por C++. Una vez definida la vari- a able, el operador de selecci´n (.) permite acceder a las funciones p´blicas o u correspondientes a la clase Complejo, aplicadas a la variable particular que nos interesa: z.setreal(3) pone en la parte real del Complejo z el n´mero u 3, y w.setreal(1.5) hace lo propio con w. 25
  • 26. 6.5 Implementaci´n de funciones miembros o Ya sabemos c´mo declarar funciones miembros en el interior de la clase y o c´mo usarlas. Ahora veamos c´mo se implementan. o o void Complejo::setreal(double x) { real = x; } void Complejo::setimag(double x) { imag = x; } double Complejo::getreal() { return real; } double Complejo::getimag() { return imaginaria; } Como toda funci´n, primero va el tipo de la funci´n (void o double en los o o ejemplos), luego el nombre de la funci´n y los argumentos. Finalmente la o implementaci´n. Lo diferente es que el nombre va precedido del nombre de o la clase y el operador “::” . 6.6 Constructor Al declarar una variable, el programa crea el espacio de memoria suficiente para alojarla. Cuando se trata de variables de tipos predefinidos en C++ esto no es problema, pero cuando son tipos definidos por el usuario C++ debe saber c´mo construir ese espacio. La funci´n que realiza esa tarea se o o denomina constructor. El constructor es una funci´n p´blica de la clase, que tiene el mismo o u nombre que ella. Agreguemos un constructor a la clase Complejo: 26
  • 27. class Complejo { private: double real,imaginaria; public: Complejo(double,double); void setreal(double); void setimag(double); double getreal(); double getimag(); }; Complejo::Complejo (double x, double y): real(x), imaginaria(y) { } Definir el constructor de esta manera nos permite crear en nuestro pro- grama variables de tipo Complejo y asignarles valores sin usar setreal() o setimag(): Complejo z (2, 3.8); Complejo w = Complejo(6.8, -3); En el constructor se inicializan las variables internas que nos interesa inicializar al momento de crear un objeto de esta clase. Si una de las variables internas a inicializar es una cadena de caracteres, hay que inicializarla de modo un poco distinto. Por ejemplo, si estamos ha- ciendo una clase Persona que s´lo tenga el nombre de una persona, entonces o podemos definir la clase y su constructor en la forma: class Persona { private: char nombre[20]; public: Persona(char []); }; 27
  • 28. Persona::Persona(a[]) { strcpy(nombre,a); } Si uno no especifica el constructor de una clase C++ crea uno default, pero en general ser´ insuficiente para cualquier aplicaci´n realmente pr´ctica. a o a Es una mala costumbre ser descuidado y dejar estas decisiones al computador. 6.7 Destructor As´ como es necesario crear espacio de memoria al definir una variable, ı hay que deshacerse de ese espacio cuando la variable deja de ser necesaria. En otras palabras, la clase necesita tambi´n un destructor . Si la clase es e Complejo, el destructor es una funci´n p´blica de ella, llamada ~Complejo. o u class Complejo { private: double real, imaginaria; public: Complejo(double,double); ~Complejo(void); void setreal(double); void setimag(double); double getreal(); double getimag(); }; Complejo::Complejo (double x, double y): real(x), imaginaria(y) { } Complejo::~Complejo(void) { } Como con los constructores, al omitir un destructor C++ genera uno default, pero es una mala costumbre. . . , etc. 28
  • 29. 6.8 Matrices de clases Una clase es un tipo de variable como cualquier otro de los predefinidos en C++. Es posible construir matrices con ellas, del mismo modo que uno tiene matrices de enteros o caracteres. La unica diferencia con las matrices ´ usuales es que no se pueden s´lo declarar, sino que hay que inicializarlas o simult´neamente. Por ejemplo, si queremos crear una matriz que contenga a 2 n´meros complejos, la l´ u ınea Complejo z[2]; es incorrecta, pero s´ es aceptable la l´ ı ınea Complejo z[2] = {Complejo(3.5,-0.8), Complejo(-2,4)}; 7 Sobrecarga Para que la definici´n de nuevos objetos sea realmente util, hay que ser ca- o ´ paz de hacer con ellos muchas acciones que nos ser´ naturales. Como ya ıan comentamos al introducir el concepto de clase, nos gustar´ sumar n´meros ıa u complejos, y que esa suma utilizara el mismo signo + de la suma usual. O extraerles la ra´ cuadrada, y que la operaci´n sea tan f´cil como escribir ız o a sqrt(z). Lo que estamos pidiendo es que el operador + o la funci´n sqrt() o sean polim´rficos, es decir, que act´e de distinto modo seg´n el tipo de ar- o u u gumento que se le entregue. Si z es un real, sqrt(z) calcular´ la ra´ de un a ız n´mero real; si es complejo, calcular´ la ra´ de un n´mero complejo. u a ız u La t´cnica de programaci´n mediante la cual podemos definir funciones e o polim´rficas se llama sobrecarga. o 7.1 Sobrecarga de funciones Digamos que la ra´ cuadrada de un n´mero complejo a + ib es (a/2) + i(b/2). ız u (Es m´s complicado en realidad, pero no queremos escribir las f´rmulas a o ahora.) Para sobrecargar la funci´n sqrt() de modo que acepte n´meros com- o u plejos basta definirla as´ ı: 29
  • 30. Complejo sqrt(Complejo z) { return Complejo (z.getreal()/2, z.getimag()/2); } Observemos que definimos una funci´n sqrt que acepta argumentos de tipo o Complejo, y que entrega un n´mero del mismo tipo. Cuando pidamos la ra´ u ız de un n´mero, el computador se preguntar´ si el n´mero en cuesti´n es un u a u o int, double, float o Complejo, y seg´n eso escoger´ la versi´n de sqrt que u a o corresponda. Con la definici´n anterior podemos obtener la ra´ cuadrada de un n´mero o ız u complejo simplemente con las instrucciones: Complejo z(1,3); Complejo raiz = sqrt(z); 7.2 Sobrecarga de operadores ¿C´mo le decimos al computador que el signo + tambi´n puede aceptar o e n´meros complejos? La respuesta es f´cil, porque para C++ un operador u a no es sino una funci´n, y la acci´n de sobrecargar que ya vimos sirve en este o o caso tambi´n. La sintaxis es: e Complejo operator + (Complejo z, Complejo w) { return Complejo (z.getreal() + w.getreal(), z.getimag() + w.getimag()); } 7.3 Coerci´n o Sabemos definir a + b, con a y b complejos. Pero ¿qu´ pasa si a o b son e enteros? ¿O reales? Pareciera que tendr´ ıamos que definir no s´lo o Complejo operator + (Complejo a, Complejo b); sino tambi´n todas las combinaciones restantes: e Complejo operator + (Complejo a, int b); Complejo operator + (Complejo a, float b); Complejo operator + (int a, Complejo b); 30
  • 31. etc´tera. e En realidad esto no es necesario. Por cierto, un n´mero real es un n´mero u u complejo con parte imaginaria nula, y es posible hacerle saber esto a C++, usando la posibilidad de definir funciones con par´metros default. Basta a declarar (en el interior de la clase) el constructor de los n´meros complejos u como Complejo (double, double = 0); Esto permite definir un n´mero complejo con la instrucci´n: u o Complejo c = Complejo(3.5); resultando el n´mero complejo 3.5 + i · 0. Y si tenemos una l´ u ınea del tipo: Complejo c = Complejo(3,2.8) + 5; el computador convertir´ impl´ a ıcitamente el entero 5 a Complejo (sabe como hacerlo porque el constructor de n´meros complejos acepta tambi´n un solo u e argumento en vez de dos), y luego realizar´ la suma entre dos complejos, que a es entonces la unica que es necesario definir. ´ 8 Punteros Una de las ventajas de C++ es permitir el acceso directo del programador a zonas de memoria, ya sea para crearlas, asignarles un valor o destruirlas. Para ello, adem´s de los tipos de variables ya conocidos (int, double, clases), a C++ proporciona un nuevo tipo: el puntero. El puntero no contiene el valor de una variable, sino la direcci´n de memoria en la cual dicha variable se o encuentra. Un peque˜o ejemplo nos permite ver la diferencia entre un puntero y la n variable a la cual ese puntero “apunta”: void main() { int i = 42; int * p_i = &i; cout << "El valor del puntero es: " << p_i << endl; cout << "Y apunta a la variable: " << *p_i << endl; } 31
  • 32. En este programa definimos una variable i entera, y luego un puntero a esa variable, que en este caso denominamos p_i. Observemos la presencia de los s´ ımbolos * y &. Al ejecutar este programa, veremos en pantalla una primera l´ınea que nos da el valor del puntero, donde encontraremos alg´n u n´mero hexadecimal imposible de determinar a priori, y que corresponde a u la direcci´n de memoria donde qued´ ubicada la variable i. La segunda l´ o o ınea nos da el valor de la variable que est´ en esa direcci´n de memoria: 42. a o Los punteros tienen gran importancia cuando de manejar datos din´micos a se trata, es decir, objetos que son creados durante la ejecuci´n del programa, o en n´mero imposible de predecir al momento de compilar. Por ejemplo, una u aplicaci´n Windows normal que crea una, dos, tres, etc. ventanas a medida o que uno abre archivos. En este caso, cada ventana es un objeto din´mico, a creado durante la ejecuci´n, y la unica forma de manejarlo es a trav´s de un o ´ e puntero a ese objeto. 9 Herencia Herencia es el mecanismo mediante el cual es posible definir clases a partir de otras, preservando parte de las propiedades de la primera y agregando o modificando otras. Por ejemplo, si definimos la clase Persona, toda Persona tendr´ una a variable miembro que sea su nombre. Si definimos una clase Hombre, tambi´ne ser´ Persona, y por tanto deber´ tener nombre. Pero adem´s puede tener a ıa a esposa. Y ciertamente no toda Persona tiene esposa. S´lo un Hombre. o C++ provee mecanismos para implementar estas relaciones l´gicas y o poder definir una clase Hombre a partir de Persona. Lo vemos en el siguiente ejemplo: class Persona { private: char nombre[20]; public: Persona(char [] = ""); ~Persona(void); char getname(); } 32
  • 33. class Hombre : public Persona { private: char esposa[20]; public: Hombre(char a[]) : Persona(a) { }; char getwife(); void setwife(); } Primero definimos una clase Persona que tiene nombre. Luego definimos una clase Hombre a partir de Persona (con la l´ınea class Hombre : public Persona). Esto permite de modo autom´tico que Hombre tenga tambi´n una a e variable nombre. Y finalmente, dentro de la clase Hombre, se definen todas aquellas caracter´ ısticas adicionales que una Persona no tiene pero un Hombre s´ esposa, y funciones miembros para modificar y obtener el nombre de ella. ı: Un ejemplo de uso de estas dos clases: Persona cocinera("Maria"); Hombre panadero("Claudio"); panadero.setwife("Estela"); cout << cocinera.getname() << endl; cout << panadero.getname() << endl; cout << panadero.getwife() << endl; Observemos que panadero tambi´n tiene una funci´n getname(), a pe- e o sar de que la clase Hombre no la define expl´ ıcitamente. Esta funci´n se ha o heredado de la clase de la cual Hombre se ha derivado, Persona. 33