P O O
PM     EL LENGUAJE C++ Y LA POO
       Algunas diferencias entre C y C++
       Objetos, métodos, encapsulado.
Tema
           Clases
           Métodos
           Constructores y Destructores


2          Sobrecarga
           Amigos
           Entrada y salida en C++
           Espacios de nombres
           Miembros estáticos
                                           PM. 2. POO 1
Classes




          PM. 2. POO 2
Classes

La mayor diferencia entre C y C++ está en
  soporte que este último ofrece para las
                  clases




                                     PM. 2. POO 2
Classes

La mayor diferencia entre C y C++ está en
  soporte que este último ofrece para las
                  clases
  El nombre original de C++ era "C with
                Classes"




                                     PM. 2. POO 2
Classes

La mayor diferencia entre C y C++ está en
  soporte que este último ofrece para las
                  clases
  El nombre original de C++ era "C with
                Classes"
      Esencialmente una clase es una




                                     PM. 2. POO 2
Classes

La mayor diferencia entre C y C++ está en
  soporte que este último ofrece para las
                  clases
  El nombre original de C++ era "C with
                Classes"
      Esencialmente una clase es una

     Estructura de datos junto a
      operadores para acceder y
             modificarlos
                                     PM. 2. POO 2
Cómo se usaría una clase




                           PM. 2. POO 3
Cómo se usaría una clase


Se puede definir una clase "Complejo" y
variables de tipo Complejo:
    int main()
    {
         Complejo c1, c2, c3;
         …



                                          PM. 2. POO 3
Cómo se usaría una clase


Se puede definir una clase "Complejo" y
variables de tipo Complejo:
    int main()
    {
         Complejo c1, c2, c3;
         …



                                          PM. 2. POO 3
Clases, declaración




                      PM. 2. POO 4
Clases, declaración
La declaración es muy parecida a la declaración
de estructuras, de la que son extensión:

   struct Complejo {
    class
         float parteReal;
         float parteImaginaria;
    };



                                          PM. 2. POO 4
Clases, declaración
La declaración es muy parecida a la declaración
de estructuras, de la que son extensión:

     class Complejo {
          float parteReal;
          float parteImaginaria;
     };



                                          PM. 2. POO 4
Clases, declaración
La declaración es muy parecida a la declaración
de estructuras, de la que son extensión:

     class Complejo {
          float parteReal;
          float parteImaginaria;
     };
        Los campos son ahora llamados


                                          PM. 2. POO 4
Clases, declaración
La declaración es muy parecida a la declaración
de estructuras, de la que son extensión:

     class Complejo {
          float parteReal;
          float parteImaginaria;
     };
        Los campos son ahora llamados
                  atributos
                                          PM. 2. POO 4
Clases, declaración
La declaración es muy parecida a la declaración
de estructuras, de la que son extensión:

     class Complejo {
          float parteReal;
          float parteImaginaria;
     };
        Los campos son ahora llamados
                  atributos
                 de la clase.
                                          PM. 2. POO 4
Las class permiten recoger más cosas




                                 PM. 2. POO 5
Las class permiten recoger más cosas




Puede haber también tipos, constantes, etc.




                                         PM. 2. POO 5
MÉTODOS

class Complejo {
     typedef TUno int;
     float parteReal;
     float parteImaginaria;

};


Las funciones dentro son ahora llamados

de la clase.                         PM. 2. POO 6
MÉTODOS

class Complejo {
     typedef TUno int;
     float parteReal;
     float parteImaginaria;
                               métodos
};


Las funciones dentro son ahora llamados

de la clase.                         PM. 2. POO 6
MÉTODOS

class Complejo {
     typedef TUno int;
     float parteReal;
     float parteImaginaria;
     void dividepor(float d); métodos
};


Las funciones dentro son ahora llamados

de la clase.                         PM. 2. POO 6
MÉTODOS

class Complejo {
     typedef TUno int;
     float parteReal;
     float parteImaginaria;
     void dividepor(float d);
};


Las funciones dentro son ahora llamados
                métodos
de la clase.                          PM. 2. POO 6
Clases, uso

Una vez declarada la clase, se pueden crear
 objetos de esa clase:

               Complejo c1, c2;

  Los objetos c1 y c2 son instancias de la
               clase Complejo


                                         PM. 2. POO 7
Los atributos están ocultos

                   atributos,
                    métodos, tipos,
En una class        constantes, etc

               los miembros están

por defecto




                                      PM. 2. POO 8
Los atributos están ocultos

                   atributos,
                    métodos, tipos,
En una class        constantes, etc

               los miembros están ocultos

por defecto




                                        PM. 2. POO 8
Los atributos están ocultos

                   atributos,
                    métodos, tipos,
En una class        constantes, etc

               los miembros están ocultos

por defecto

                son inaccesibles



                                        PM. 2. POO 8
ocultos…




           PM. 2. POO 9
ocultos…

int main() {




                          PM. 2. POO 9
ocultos…

int main() {
    class CComplejo { float re, im; };




                                         PM. 2. POO 9
ocultos…

int main() {
    class CComplejo { float re, im; };
    CComplejo c1;




                                         PM. 2. POO 9
ocultos…

int main() {
    class CComplejo { float re, im; };
    CComplejo c1;
   c1.parteReal = 0.0;




                                         PM. 2. POO 9
ocultos…

int main() {
    class CComplejo { float re, im; };
    CComplejo c1;
   c1.parteReal = 0.0;
   im = c2.parteImaginaria;



 Decimos que parteReal y parteImaginaria son
 miembros privados de la clase Complejo.

                                               PM. 2. POO 9
ocultos…

int main() {
    class CComplejo { float re, im; };
    CComplejo c1;
   c1.parteReal = 0.0;
   im = c2.parteImaginaria;



 Decimos que parteReal y parteImaginaria son
 miembros privados de la clase Complejo.

                                               PM. 2. POO 9
ocultos…

int main() {
    class CComplejo { float re, im; };
    CComplejo c1;
                              ilegal,
   c1.parteReal = 0.0;
                              los atributos no son
   im = c2.parteImaginaria;
                                 accesibles


 Decimos que parteReal y parteImaginaria son
 miembros privados de la clase Complejo.

                                               PM. 2. POO 9
Atributos public




                   PM. 2. POO 10
Atributos public

 Si queremos permitir     class Complejo {
el acceso desde fuera     public:
a los atributos de una      float parteReal;
         clase hay que      float parteImaginaria;
  declararlos públicos:   };




                                                     PM. 2. POO 10
Atributos public

 Si queremos permitir     class Complejo {
el acceso desde fuera     public:
a los atributos de una      float parteReal;
         clase hay que      float parteImaginaria;
  declararlos públicos:   };


                          class Complejo {
            Podemos
                          public:
    combinar partes
                            float parteReal;
  públicas y privadas
                          private:
        de una clase:
                            float parteImaginaria;
                          };
                                                     PM. 2. POO 10
Miembros
 Si no son visibles los miembros privados de
                  una clase…
¿cómo se pueden modificar o ver sus valores?
           La respuesta es simple:




                                       PM. 2. POO 11
Miembros
 Si no son visibles los miembros privados de
                  una clase…
¿cómo se pueden modificar o ver sus valores?
           La respuesta es simple:

Las funciones que necesiten acceder a
los datos miembros de una clase deben
estar declarados
         dentro de la misma clase


                                       PM. 2. POO 11
Miembros
 Si no son visibles los miembros privados de
                  una clase…
¿cómo se pueden modificar o ver sus valores?
           La respuesta es simple:

Las funciones que necesiten acceder a
los datos miembros de una clase deben
estar declarados
         dentro de la misma clase
Son las funciones miembro o métodos.
                                       PM. 2. POO 11
Diferencia con las estructuras

En resumen
• Para controlar el uso de la información que
  determina el estado de un objeto se deben
  usar métodos
• Un objeto tiene un estado interno sólo
  reconocible por las respuestas a las llamadas
  a sus métodos
• Para modificar el estado de un objeto se
  debe llamar a sus métodos de acceso
                                          PM. 2. POO 12
Ejemplo de métodos

class Complejo {
public:
  void crear(int preal, int pimag);
  void print();
private:
  float parteReal;
  float parteImaginaria;
};
                                  PM. 2. POO 13
Métodos públicos y privados

 Vemos que los métodos pueden ser
 declarados:

• en la parte pública: son la interfaz de
  uso
• en la parte privada: procedimientos
  internos necesarios para el
  funcionamiento del objeto.
                                       PM. 2. POO 14
Ejemplo

                 class Fraccion {
                 public:
interfaz de        void crear(int num, int denom);
uso
                   void print();
                 private:
procedimientos
internos
                   void reduce();
atributos
                   int numerador, denominador;
                 }


                                                     PM. 2. POO 15
Métodos, ¿dónde se desarrollan?
Aunque los métodos se ponen dentro de la
 clase, sólo se pone su prototipo, no su
 cuerpo
   class Fraccion {
   public:
     void crear(int num, int denom);
   };

Para desarrollar el cuerpo se necesita
referirse al método desde fuera de la clase.
                                           PM. 2. POO 16
Métodos, ¿dónde se desarrollan?
class Fraccion {
public:
  void crear(int num, int denom);
};

void Fraccion::crear(int num, int denom)
{
  código de crear…
}

                                      PM. 2. POO 17
Cuerpo de los métodos

La mayoría de los métodos no se desarrollan
en línea, sino que el desarrollo (los cuerpos de
los métodos) se desarrollan en el fichero
pareja de la cabecera .h y que sería .cpp
                       ♥
                .h          .cpp

dentro de él se accede a los miembros de la
clase mediante la notación de ámbito
     nombreClase::
                                           PM. 2. POO 18
Cuerpo de los métodos
naves.h




                                  PM. 2. POO 19
Cuerpo de los métodos
          class Nave {
naves.h     public:
              Nave(const int x=0, const int y=0);
              void Mover(const int dx, const int dy);
            ...
          }




                                                        PM. 2. POO 19
Cuerpo de los métodos
            class Nave {
 naves.h      public:
                Nave(const int x=0, const int y=0);
                void Mover(const int dx, const int dy);
              ...
            }


            #include “naves.h”
naves.cpp   Nave:: Nave(const int x, const int y) {
               X=x;Y=y;
            }
            void Nave:: Mover(const int dx, const int dy) {
               X += dx;
               Y += dy;
            }
                                                              PM. 2. POO 19
Ejemplo: complejo.cpp
#include <iostream>
#include <cstdlib>
#include "complejo.h"    // …al final de los includes



Complejo::pon(const int re, const int im)
  {
  real = re;
  imag = im;
}
Complejo::print() {
  cout << real <<"+ i "<<imag;
}
                                                   PM. 2. POO 20
Uso de una clase


Para usar una clase hay que importar su
               descripción

(la declaración de la clase que está en la
              cabecera .h)

y crear objetos, etcétera, en el programa:


                                       PM. 2. POO 21
Uso de una clase
           ojo:
 se importa clase.h tanto en
clase.cpp como en prueba.cpp
                     clase.h


#include "clase.h"         #include "clase.h"


    clase.cpp                  prueba.cpp



                                                PM. 2. POO 22
++Compilación++


Tenemos más de un fuente (.cpp)
   ¿cómo compilarlos juntos?

  c++      clase.cpp prueba.cpp                  a.out


  Si lo tenemos todo en un directorio bastaría con:


               c++ *.cpp
                                                      PM. 2. POO 23
PM. 2. POO 24
Construir, como ejemplo, los tres
ficheros correspondientes a una
     clase CComplejo y un
     PruebaComplejo.cpp



                              PM. 2. POO 24
Construir, como ejemplo, los tres
ficheros correspondientes a una
     clase CComplejo y un
     PruebaComplejo.cpp



                              PM. 2. POO 24
Métodos especializados




                         PM. 2. POO 25
Métodos especializados




• En la mayoría de las clases es necesario dar
  valores iniciales a sus atributos:

                   Constructor




                                          PM. 2. POO 25
Constructor




              PM. 2. POO 26
Constructor


‣ Sería el miembro público cuyo nombre es el
 mismo que el de la clase, sin devolver nada,
 ni void




                                        PM. 2. POO 26
Constructor


‣ Sería el miembro público cuyo nombre es el
 mismo que el de la clase, sin devolver nada,
 ni void

‣ Puede llevar parámetros




                                        PM. 2. POO 26
Constructor


‣ Sería el miembro público cuyo nombre es el
 mismo que el de la clase, sin devolver nada,
 ni void

‣ Puede llevar parámetros

‣ Puede haber varios con distintas signaturas


                                         PM. 2. POO 26
Ejemplo: complejo.h

              class CComplejo {
                                         constructor automático
              public:
                 CComplejo(int re=0, int im=1)
interfaz de
uso
                 void print() const; // no modif. objeto
                 void pon(const int re=0, const int im=1);
              private:
                 int real, imag;
atributos
              };

              CComplejo c1(3,2), c2;
                                                          PM. 2. POO 27
Constructor, casos
Ejemplos de uso de Constructor

Según encajen pueden ser llamados un
  constructor u otro.

     CComplejo c(10, -2), c2(5,4), c3[8];

                            al no poderse poner valores
                          para cada elemento debe haber
                           un constructor sin parámetros
                               con valores por defecto


                                                  PM. 2. POO 28
Ejemplo: prucomp.cpp

#include <iostream.h>
#include "complejo.h"
                           llamada
                  implícita a constructor
int main() {           del objeto
  CComplejo c1;
  c1.print(); cout << endl;
  c1.pon(2,-3);
  c1.print(); cout << endl;
}

                                            PM. 2. POO 29
Construcción por copia de objetos


• Constructor por copia
  – Sería el miembro público cuyo nombre es el
    mismo que el de la clase y cuyo único argumento
    es un objeto de la clase en modo const clase&

  CComplejo sin(3,2);
  CComplejo sin(con); // actua constructor por copia

• No siempre hace falta.

                                             PM. 2. POO 30
Construcción por copia de objetos


La construcción por copia se "ejecuta" con la
    declaración:

• explícita en la creación:
             CMatriz m2 = m1;



• implícita en la creación:
            CMatriz m3(m1);

                                                PM. 2. POO 31
Copia errónea de objetos
La iniciación de objetos durante la construcción admite pues
   diversas formas:

  class T {
    public:
      T(); // Creador sin parámetros
      T(tipo uno); // Creador con un parámetro
      T(const T& de); // constructor por copia…

PERO SI NO HAY UN OPERADOR DE COPIA, EN GENERAL:
  ...
  t1 = t2;
  ...
YA QUE hará sólo la copia de los atributos y no se hará la
  construcción de la estructura correcta de una nueva copia.


                                                               PM. 2. POO 32
Copia errónea de objetos
La iniciación de objetos durante la construcción admite pues
   diversas formas:

  class T {
    public:
      T(); // Creador sin parámetros
      T(tipo uno); // Creador con un parámetro
      T(const T& de); // constructor por copia…

PERO SI NO HAY UN OPERADOR DE COPIA, EN GENERAL:
  ...
  t1 = t2;  ERROR
  ...
YA QUE hará sólo la copia de los atributos y no se hará la
  construcción de la estructura correcta de una nueva copia.


                                                               PM. 2. POO 32
Ejemplo: matriz.h
class Matriz {
 public:
     Matriz(int n, int m);                    constructor
     Matriz(const Matriz& origen);            constructor por copia
     ~Matriz(void);


     int ver(const int fila,const int col);
     void pon(const int fila,const int col,const int x);
     void dims(int &n, int &m) {n=N;m=M;};
 private:
     int N, M;
     int *datos;
};
                                                           PM. 2. POO 33
Métodos destructor




                     PM. 2. POO 34
Métodos destructor


• Destructor




                                    PM. 2. POO 34
Métodos destructor


• Destructor

  – Miembro público cuyo nombre es el mismo que el
    de la clase con un ~ delante




                                            PM. 2. POO 34
Métodos destructor


• Destructor

  – Miembro público cuyo nombre es el mismo que el
    de la clase con un ~ delante
  – No devolver nada, ni void




                                            PM. 2. POO 34
Métodos destructor


• Destructor

  – Miembro público cuyo nombre es el mismo que el
    de la clase con un ~ delante
  – No devolver nada, ni void
  – No parámetros




                                            PM. 2. POO 34
Métodos destructor


• Destructor

  – Miembro público cuyo nombre es el mismo que el
    de la clase con un ~ delante
  – No devolver nada, ni void
  – No parámetros




                                            PM. 2. POO 34
Métodos destructor


• Destructor

  – Miembro público cuyo nombre es el mismo que el
    de la clase con un ~ delante
  – No devolver nada, ni void
  – No parámetros




                                            PM. 2. POO 34
Destrucción implícita


La destrucción implícita se llama sola,
  automáticamente, cuando el objeto deja de
  estar accesible, por ejemplo, al acabar el
  ámbito de su visibilidad

La destrucción puede llamarse explícitamente llamando al
  método de destrucción aunque esto último suele ser
  innecesario



                                                      PM. 2. POO 35
Peligro de la copia de parámetros

Peor ocurre aún, si hacemos una llamada a una función
   externa como:
       ...
       pinta(t1);
       ...
siendo

      void pinta(const T t1)

los resultados serán igualmente desastrosos.


                       ¿Por qué?
                                                 PM. 2. POO 36
Peligro de la copia de parámetros
El motivo es que pinta(t1) construye una copia (mal) de
   t1 para el parámetro local de pinta y al acabar pinta()
   destruye esa copia destruyendo de camino el original.

Una solución es hacer

      void pinta(const T& t)

• sea, declarar el parámetro como referencia constante

   – No se copia
   – No se cambia



                                                      PM. 2. POO 37
Peligro de la copia de parámetros

Al recibirse el objeto por referencia no hay
  destrucción automática al acabar el
  procedimiento y no habrá sorpresas en los
  casos de memoria dinámica enlazada como
  veremos.


       void pinta(const T& t)


                                           PM. 2. POO 38
Operador de asignación =

Pero el problema de la copia es más general: sólo
  hemos visto como evitarlo durante la creación por
  copia y durante el paso de parámetros.
Para que la operación = funcione correctamente con
  nuestros objetos particulares hará falta
  sobrecargar el operador asignación con nuestro
  algoritmo particular de copiado.


  T& operator= (const T& orig);

                                             PM. 2. POO 39
Copia por asignación de objetos en general
 ejemplo:


   class T {
     public:
       T(); // Creador sin parámetros
       T(tipo uno); // Creador con un parámetro
       T(const T& de); // constructor por copia


      T& operator= (const T& de); // operador de copia

       ....


                                                   PM. 2. POO 40
Las relaciones entre classes
A veces es conveniente que otra
clase pueda ver mi parte privada

  cuando se quiere delegar una
operación común a otra clase que
  necesitaría ver nuestra parte
      privada para hacerla


                                   PM. 2. POO 41
AMISTAD entre clases
    ¿Puede ser posible que
        otra clase
acceda a nuestra parte privada?




                             PM. 2. POO 42
AMISTAD entre clases
    ¿Puede ser posible que
        otra clase
acceda a nuestra parte privada?



          Sí
                             PM. 2. POO 42
amistad entre clases


 permiso
garantizado




                         PM. 2. POO 43
amistad entre clases


            permiso
           garantizado

class Una {               class Otra {
  friend class Otra;        void metodo2(Una u) {
 private:                     u.atri = 33;
  int atri;                   u.metodo();
  void metodo();            }
};                        };


                                           PM. 2. POO 43
Sobrecarga de <<
Si se define la clase ostream que tiene el
  operador a << como amiga
friend ostream& operator<<(ostream &os, const Text& orig);


y se desarrolla como por ejemplo:
 ostream& operator<<(ostream &os, const Text& orig)
 {
   os << orig.s; // accede a su parte privada
   return os;
 }


                                                      PM. 2. POO 44
class Text {
                  public:                                                     uso:
                    Text(const char* txtPtr);
                    Text() : s(0) {};
                    ~Text();
                    Text(const Text& orig);
                    bool operator== (const Text& derecho) const;              t1 == t2
Ejemplo +completo



                    char operator[ ] (unsigned long indice) const;            t1[33]
                    unsigned long Longitud() const;
                    void pinta(const bool nl = true) const;
                    friend Text operator+ (const Text& ls, const Text& rs);   t3 = t1 + t2
                    operator const char*() const;                             (char*) (t2)
                    Text& operator= (const Text& orig);                       t1 = t2
                    Text& operator= (const char *str);                        t1 = "abc"
                                                                              cout << t1;
                    friend ostream& operator<<(ostream &os, const Text&
                    orig);
                  private:
                    char *s; // la cadena C
                    unsigned long l;
                    unsigned long strlen(const char *str) const;
                     void strasigna(const char *desde);
                     bool strcmp(const char *con) const;
                };                                                                       45
#include <iostream.h>                    bool Text::operator== (const Text&
                                                                   derecho) const {
                    #include "text.h"
                                                                 if (derecho.l == 0 && 0 == l)
                                                                   return true;
                    // Constructor desde cadena C                else
Ejemplo +completo


                    Text::Text(const char* txtPtr) : s(0),           return strcmp(derecho.s);
                       l(0) {                                 }
                        if (txtPtr != 0)                     char Text::operator[] (unsigned long
                                                                   indice) const {
                           strasigna(txtPtr);
                                                                 if (0 <= indice && indice < l)
                    }                                                return s[indice];
                    // Constructor de copia                      else
                    Text::Text(const Text& orig) : s(0),             return '0';
                       l(orig.l) {                           }
                        if (orig.l != 0)                     // averigua la longitud
                                                             unsigned long Text::Longitud() const {
                           strasigna(orig.s);
                                                                 return l;
                    }
                                                             }
                    // destructor                            // Adapta el tipo (cast) a cadena C
                    Text::~Text() {                          Text::operator const char*() const {
                        delete[] s;                              return s;
                    }                                        }                                        46
// Operador de asignación                   unsigned long Text::strlen(const char *str)
                    Text& Text::operator= (const Text& orig)        const {
                         {                                        unsigned long n = 0;
                       // evita a = a;                            while (str[n])
                       if (this == &orig)                            n++;
Ejemplo +completo

                           return *this;                          return n;
                       if (l != 0) {                            }
                           delete[] s;                          void Text::strasigna(const char *desde) {
                           l = 0;                                 unsigned long i = 0;
                                                                  l = strlen(desde);
                       }
                                                                  s = new char[l+1];
                       if (orig.l)
                                                                  while (s[i] = desde[i])
                           strasigna(orig.s);
                                                                     i++;
                       return *this;
                                                                }
                    }
                                                                bool Text::strcmp(const char *con) const
                    // Operador de asignación desde una str     {
                    Text& Text::operator= (const char *str) {     unsigned long i = 0;
                       if (l != 0) {                              while (s[i] && con[i] && s[i] == con[i])
                           delete[] s;                               i++;
                           l = 0;                                 return s[i] == '0' && con[i] == '0';
                       }                                        }
                       if (str != 0)
                           strasigna(str);
                       return *this;
                    }
                                                                                                              47
// amigo que permite sobrecargar '+' para concatenar Texts
                    Text operator+ (const Text& ls, const Text& rs) {
                        Text ret;
                        unsigned long i=0, ii=0;
Ejemplo +completo

                        ret.l = ls.l + rs.l;
                        ret.s = new char[ret.l+1];
                        ret.s[0] = '0';
                        if (ls.s != NULL) {
                            while (ret.s[i] = ls.s[i])
                                i++;
                            ii = i-1;
                            i = 0;
                        }
                        if (rs.s != NULL)
                            while (ret.s[ii] = rs.s[i])
                               i++; ii++;
                        return ret;
                    }
                    ostream& operator<<(ostream &os, const Text& orig) {
                                                                                 48
espacios de nombres


Una declaración accesible en todo el programa
 es una declaración global.

La colección de todas las declaraciones se
  denomina espacio de nombres global.




                                             PM. 2. POO 49
using namespace
C++, sin embargo, proporciona a los programadores
 la posibilidad de situar las declaraciones en
 espacios de nombres definidos por el programa.

  namespace nombre {
    void f() { cout << desde f en nombre<<endl;
  };

la llamada hay que hacerla:

    nombre::f();

excepto que se ponga antes:

    using namespace nombre;                       PM. 2. POO 50
librerías con namespace
Las cabeceras que utilizan el espacio de
  nombres global suelen acabarse como
  clásicamente: .h

Las librerías que sitúan sus declaraciones
  dentro de espacios de nombres (no globales)
  no usan extensión.

Por ejemplo: <iostream> es un archivo de
  cabecera cuyas declaraciones están en el
  espacio de nombres std
                                           PM. 2. POO 51
librerías con namespace
Por eso hacemos:
	 #include <iostream>
	 #include <iomanip>
	 using namespace std;


	 int main () {
	    cout << setw (10);
	    cout << 77 << endl;
	    return 0;
	}
                                   PM. 2. POO 52
Miembros estáticos




                     PM. 2. POO 53
Miembros estáticos
Se pueden definir miembros (atributos o métodos)
  con el atributo static:




                                             PM. 2. POO 53
Miembros estáticos
Se pueden definir miembros (atributos o métodos)
  con el atributo static:
• Tal miembro es común a todos los objetos de tal
  clase.




                                              PM. 2. POO 53
Miembros estáticos
Se pueden definir miembros (atributos o métodos)
  con el atributo static:
• Tal miembro es común a todos los objetos de tal
  clase.
• Tales miembros existen aunque no haya ningún
  objeto de tal clase




                                              PM. 2. POO 53
Miembros estáticos
Se pueden definir miembros (atributos o métodos)
  con el atributo static:
• Tal miembro es común a todos los objetos de tal
  clase.
• Tales miembros existen aunque no haya ningún
  objeto de tal clase
• Para usarlos se puede usar un objeto cualquiera de
  los de la clase o usar el especificador de ámbito
      Clase::cuenta = 33;




                                              PM. 2. POO 53
Miembros estáticos
Se pueden definir miembros (atributos o métodos)
  con el atributo static:
• Tal miembro es común a todos los objetos de tal
  clase.
• Tales miembros existen aunque no haya ningún
  objeto de tal clase
• Para usarlos se puede usar un objeto cualquiera de
  los de la clase o usar el especificador de ámbito
      Clase::cuenta = 33;
• Pueden servir, por ejemplo, para mantener
  información global, como la cuenta de todos los
  objetos. No son datos globales, ya que mantienen
  los criterios de visibilidad.
                                              PM. 2. POO 53
STL string




http://www.cplusplus.com/reference/string/string/




                                              PM. 2. POO 54
1 #include <iostream>
 2 #include <string>
 3 using namespace std;
                                                                         Ejemplo uso
 5 int main(int argc, char *argv[]) {
 6    string s = "Juan";
                                                                            string
 7    cout << s << endl;
 8    cout << s + " Falgueras" << endl;
 9    s += " (fin)";
10     cout << s << endl;
11     cout << s.empty() << endl;
12     cout << s.length() << endl;
13     cout << s.max_size() << endl;
14     cout << s.append(" adiós") << endl;
15     cout << s.find("fin", 2) << endl;
16     cout << "En 6: " << s.at(6) << endl;
17     cout << "En 6: " << s[6] << endl;
18     cout << s.replace(6, 3, "hola") << endl;
19     cout << s.insert(10, " y adiós") << endl;
20     cout << s.erase(10, 4) << endl;
21     cout << s.substr(6, 9) << endl;
22     int i=0;
23     for(string::const_iterator it = s.begin(); it != s.end(); it++)
24          cout << i++ << " " << *it << endl;
25     getline(cin, s);
26     cout << s << endl;
27     return 0;
28 }                                                                                   55
Características especiales de la POO en C++




                                      PM. 2. POO 56
Características especiales de la POO en C++
Respecto a la POO, las características más
  importantes de C++ son:




                                             PM. 2. POO 56
Características especiales de la POO en C++
Respecto a la POO, las características más
  importantes de C++ son:




                                             PM. 2. POO 56
Características especiales de la POO en C++
Respecto a la POO, las características más
  importantes de C++ son:


• Herencia múltiple




                                             PM. 2. POO 56
Características especiales de la POO en C++
Respecto a la POO, las características más
  importantes de C++ son:


• Herencia múltiple
• Sobrecarga de operadores y funciones




                                             PM. 2. POO 56
Características especiales de la POO en C++
Respecto a la POO, las características más
  importantes de C++ son:


• Herencia múltiple
• Sobrecarga de operadores y funciones
• Derivación




                                             PM. 2. POO 56
Características especiales de la POO en C++
Respecto a la POO, las características más
  importantes de C++ son:


•   Herencia múltiple
•   Sobrecarga de operadores y funciones
•   Derivación
•   Funciones virtuales




                                             PM. 2. POO 56
Características especiales de la POO en C++
Respecto a la POO, las características más
  importantes de C++ son:


•   Herencia múltiple
•   Sobrecarga de operadores y funciones
•   Derivación
•   Funciones virtuales
•   Plantillas


                                             PM. 2. POO 56
Características especiales de la POO en C++
Respecto a la POO, las características más
  importantes de C++ son:


•   Herencia múltiple
•   Sobrecarga de operadores y funciones
•   Derivación
•   Funciones virtuales
•   Plantillas
•   Gestión de excepciones.

                                             PM. 2. POO 56
Diferencias C-C++

Se pueden sobrecargar las funciones

  void swap(int& a, int& b);
  void swap(char& a, char& b);
  void swap(int& a, int& b, bool& nose);
  bool swap(int& a, char& b);

todas son homónimas pero el compilador
  sabe en cada llamada a quién llamar por el
  tipo de argumentos que se le pongan
                                           PM. 2. POO 57
Valores por defecto

Argumentos con valor por defecto

    leehasta(char s[], int MAX, char delim = ‘n’)
      int a(int c, int a=1, int b=2)
        hace que a(1), ó a(1,2) ó a(1,2,3) no sean ambiguos
    pero
     int a(int a=1, int b=2, int c)                NO al final
        a(4,5) ??

NOTA: También se pueden dar ambigüedades si se ponen valores por defecto a
  funciones sobrecargadas

                                                                     PM. 2. POO 58
Pequeñas diferencias C-C++ (2)

Funciones inline frente a macros de preprocesador
supongamos definido

  #define cuadrado(x) (x*x)
entonces
void f(double d, int i) {
  r = cuadrado(d);   // va bien
  r = cuadrado(i++); // va mal: significa (i++*i++);
  r = cuadrado(d+1); // va mal: significa (d+1*d+1);
                     //   =          (d+d+1);
iría mejor, aunque no siempre bien:
  #define cuadrado(x) ((x)*(x))
                                            PM. 2. POO 59
Pequeñas difs. C-C++: funciones inline
sigue sin resolver cuadrado(i++)
Así que C++ aporta una solución:

           inline int icuadrado(int x) {
                 return x * x;
           }
que expande C++ (no el procesador), sí resuelve el problema:


           icuadrado(i++) // va bien
 ya que es el propio parser de C++ el que interpreta el código
                                                       PM. 2. POO 60
Pequeñas difs. C-C++: funciones inline
• La ventaja de las funciones inline es que no
  hay retraso con llamadas a función.
• Son expresiones que se repiten en el código
  cada vez que se usan sin llamar (más lento) a
  una función
• A cambio generan un código más largo

  es como una función normal pero que se
         expande entre las líneas
          del código que la llama
                                         PM. 2. POO 61
62
F I N
        62

2 POO Presentación

  • 1.
    P O O PM EL LENGUAJE C++ Y LA POO Algunas diferencias entre C y C++ Objetos, métodos, encapsulado. Tema Clases Métodos Constructores y Destructores 2 Sobrecarga Amigos Entrada y salida en C++ Espacios de nombres Miembros estáticos PM. 2. POO 1
  • 2.
    Classes PM. 2. POO 2
  • 3.
    Classes La mayor diferenciaentre C y C++ está en soporte que este último ofrece para las clases PM. 2. POO 2
  • 4.
    Classes La mayor diferenciaentre C y C++ está en soporte que este último ofrece para las clases El nombre original de C++ era "C with Classes" PM. 2. POO 2
  • 5.
    Classes La mayor diferenciaentre C y C++ está en soporte que este último ofrece para las clases El nombre original de C++ era "C with Classes" Esencialmente una clase es una PM. 2. POO 2
  • 6.
    Classes La mayor diferenciaentre C y C++ está en soporte que este último ofrece para las clases El nombre original de C++ era "C with Classes" Esencialmente una clase es una Estructura de datos junto a operadores para acceder y modificarlos PM. 2. POO 2
  • 7.
    Cómo se usaríauna clase PM. 2. POO 3
  • 8.
    Cómo se usaríauna clase Se puede definir una clase "Complejo" y variables de tipo Complejo: int main() { Complejo c1, c2, c3; … PM. 2. POO 3
  • 9.
    Cómo se usaríauna clase Se puede definir una clase "Complejo" y variables de tipo Complejo: int main() { Complejo c1, c2, c3; … PM. 2. POO 3
  • 10.
  • 11.
    Clases, declaración La declaraciónes muy parecida a la declaración de estructuras, de la que son extensión: struct Complejo { class float parteReal; float parteImaginaria; }; PM. 2. POO 4
  • 12.
    Clases, declaración La declaraciónes muy parecida a la declaración de estructuras, de la que son extensión: class Complejo { float parteReal; float parteImaginaria; }; PM. 2. POO 4
  • 13.
    Clases, declaración La declaraciónes muy parecida a la declaración de estructuras, de la que son extensión: class Complejo { float parteReal; float parteImaginaria; }; Los campos son ahora llamados PM. 2. POO 4
  • 14.
    Clases, declaración La declaraciónes muy parecida a la declaración de estructuras, de la que son extensión: class Complejo { float parteReal; float parteImaginaria; }; Los campos son ahora llamados atributos PM. 2. POO 4
  • 15.
    Clases, declaración La declaraciónes muy parecida a la declaración de estructuras, de la que son extensión: class Complejo { float parteReal; float parteImaginaria; }; Los campos son ahora llamados atributos de la clase. PM. 2. POO 4
  • 16.
    Las class permitenrecoger más cosas PM. 2. POO 5
  • 17.
    Las class permitenrecoger más cosas Puede haber también tipos, constantes, etc. PM. 2. POO 5
  • 18.
    MÉTODOS class Complejo { typedef TUno int; float parteReal; float parteImaginaria; }; Las funciones dentro son ahora llamados de la clase. PM. 2. POO 6
  • 19.
    MÉTODOS class Complejo { typedef TUno int; float parteReal; float parteImaginaria; métodos }; Las funciones dentro son ahora llamados de la clase. PM. 2. POO 6
  • 20.
    MÉTODOS class Complejo { typedef TUno int; float parteReal; float parteImaginaria; void dividepor(float d); métodos }; Las funciones dentro son ahora llamados de la clase. PM. 2. POO 6
  • 21.
    MÉTODOS class Complejo { typedef TUno int; float parteReal; float parteImaginaria; void dividepor(float d); }; Las funciones dentro son ahora llamados métodos de la clase. PM. 2. POO 6
  • 22.
    Clases, uso Una vezdeclarada la clase, se pueden crear objetos de esa clase: Complejo c1, c2; Los objetos c1 y c2 son instancias de la clase Complejo PM. 2. POO 7
  • 23.
    Los atributos estánocultos atributos, métodos, tipos, En una class constantes, etc los miembros están por defecto PM. 2. POO 8
  • 24.
    Los atributos estánocultos atributos, métodos, tipos, En una class constantes, etc los miembros están ocultos por defecto PM. 2. POO 8
  • 25.
    Los atributos estánocultos atributos, métodos, tipos, En una class constantes, etc los miembros están ocultos por defecto son inaccesibles PM. 2. POO 8
  • 26.
    ocultos… PM. 2. POO 9
  • 27.
  • 28.
    ocultos… int main() { class CComplejo { float re, im; }; PM. 2. POO 9
  • 29.
    ocultos… int main() { class CComplejo { float re, im; }; CComplejo c1; PM. 2. POO 9
  • 30.
    ocultos… int main() { class CComplejo { float re, im; }; CComplejo c1; c1.parteReal = 0.0; PM. 2. POO 9
  • 31.
    ocultos… int main() { class CComplejo { float re, im; }; CComplejo c1; c1.parteReal = 0.0; im = c2.parteImaginaria; Decimos que parteReal y parteImaginaria son miembros privados de la clase Complejo. PM. 2. POO 9
  • 32.
    ocultos… int main() { class CComplejo { float re, im; }; CComplejo c1; c1.parteReal = 0.0; im = c2.parteImaginaria; Decimos que parteReal y parteImaginaria son miembros privados de la clase Complejo. PM. 2. POO 9
  • 33.
    ocultos… int main() { class CComplejo { float re, im; }; CComplejo c1; ilegal, c1.parteReal = 0.0; los atributos no son im = c2.parteImaginaria; accesibles Decimos que parteReal y parteImaginaria son miembros privados de la clase Complejo. PM. 2. POO 9
  • 34.
    Atributos public PM. 2. POO 10
  • 35.
    Atributos public Siqueremos permitir class Complejo { el acceso desde fuera public: a los atributos de una float parteReal; clase hay que float parteImaginaria; declararlos públicos: }; PM. 2. POO 10
  • 36.
    Atributos public Siqueremos permitir class Complejo { el acceso desde fuera public: a los atributos de una float parteReal; clase hay que float parteImaginaria; declararlos públicos: }; class Complejo { Podemos public: combinar partes float parteReal; públicas y privadas private: de una clase: float parteImaginaria; }; PM. 2. POO 10
  • 37.
    Miembros Si noson visibles los miembros privados de una clase… ¿cómo se pueden modificar o ver sus valores? La respuesta es simple: PM. 2. POO 11
  • 38.
    Miembros Si noson visibles los miembros privados de una clase… ¿cómo se pueden modificar o ver sus valores? La respuesta es simple: Las funciones que necesiten acceder a los datos miembros de una clase deben estar declarados dentro de la misma clase PM. 2. POO 11
  • 39.
    Miembros Si noson visibles los miembros privados de una clase… ¿cómo se pueden modificar o ver sus valores? La respuesta es simple: Las funciones que necesiten acceder a los datos miembros de una clase deben estar declarados dentro de la misma clase Son las funciones miembro o métodos. PM. 2. POO 11
  • 40.
    Diferencia con lasestructuras En resumen • Para controlar el uso de la información que determina el estado de un objeto se deben usar métodos • Un objeto tiene un estado interno sólo reconocible por las respuestas a las llamadas a sus métodos • Para modificar el estado de un objeto se debe llamar a sus métodos de acceso PM. 2. POO 12
  • 41.
    Ejemplo de métodos classComplejo { public: void crear(int preal, int pimag); void print(); private: float parteReal; float parteImaginaria; }; PM. 2. POO 13
  • 42.
    Métodos públicos yprivados Vemos que los métodos pueden ser declarados: • en la parte pública: son la interfaz de uso • en la parte privada: procedimientos internos necesarios para el funcionamiento del objeto. PM. 2. POO 14
  • 43.
    Ejemplo class Fraccion { public: interfaz de void crear(int num, int denom); uso void print(); private: procedimientos internos void reduce(); atributos int numerador, denominador; } PM. 2. POO 15
  • 44.
    Métodos, ¿dónde sedesarrollan? Aunque los métodos se ponen dentro de la clase, sólo se pone su prototipo, no su cuerpo class Fraccion { public: void crear(int num, int denom); }; Para desarrollar el cuerpo se necesita referirse al método desde fuera de la clase. PM. 2. POO 16
  • 45.
    Métodos, ¿dónde sedesarrollan? class Fraccion { public: void crear(int num, int denom); }; void Fraccion::crear(int num, int denom) { código de crear… } PM. 2. POO 17
  • 46.
    Cuerpo de losmétodos La mayoría de los métodos no se desarrollan en línea, sino que el desarrollo (los cuerpos de los métodos) se desarrollan en el fichero pareja de la cabecera .h y que sería .cpp ♥ .h .cpp dentro de él se accede a los miembros de la clase mediante la notación de ámbito nombreClase:: PM. 2. POO 18
  • 47.
    Cuerpo de losmétodos naves.h PM. 2. POO 19
  • 48.
    Cuerpo de losmétodos class Nave { naves.h public: Nave(const int x=0, const int y=0); void Mover(const int dx, const int dy); ... } PM. 2. POO 19
  • 49.
    Cuerpo de losmétodos class Nave { naves.h public: Nave(const int x=0, const int y=0); void Mover(const int dx, const int dy); ... } #include “naves.h” naves.cpp Nave:: Nave(const int x, const int y) { X=x;Y=y; } void Nave:: Mover(const int dx, const int dy) { X += dx; Y += dy; } PM. 2. POO 19
  • 50.
    Ejemplo: complejo.cpp #include <iostream> #include<cstdlib> #include "complejo.h" // …al final de los includes Complejo::pon(const int re, const int im) { real = re; imag = im; } Complejo::print() { cout << real <<"+ i "<<imag; } PM. 2. POO 20
  • 51.
    Uso de unaclase Para usar una clase hay que importar su descripción (la declaración de la clase que está en la cabecera .h) y crear objetos, etcétera, en el programa: PM. 2. POO 21
  • 52.
    Uso de unaclase ojo: se importa clase.h tanto en clase.cpp como en prueba.cpp clase.h #include "clase.h" #include "clase.h" clase.cpp prueba.cpp PM. 2. POO 22
  • 53.
    ++Compilación++ Tenemos más deun fuente (.cpp) ¿cómo compilarlos juntos? c++ clase.cpp prueba.cpp a.out Si lo tenemos todo en un directorio bastaría con: c++ *.cpp PM. 2. POO 23
  • 54.
  • 55.
    Construir, como ejemplo,los tres ficheros correspondientes a una clase CComplejo y un PruebaComplejo.cpp PM. 2. POO 24
  • 56.
    Construir, como ejemplo,los tres ficheros correspondientes a una clase CComplejo y un PruebaComplejo.cpp PM. 2. POO 24
  • 57.
  • 58.
    Métodos especializados • Enla mayoría de las clases es necesario dar valores iniciales a sus atributos: Constructor PM. 2. POO 25
  • 59.
    Constructor PM. 2. POO 26
  • 60.
    Constructor ‣ Sería elmiembro público cuyo nombre es el mismo que el de la clase, sin devolver nada, ni void PM. 2. POO 26
  • 61.
    Constructor ‣ Sería elmiembro público cuyo nombre es el mismo que el de la clase, sin devolver nada, ni void ‣ Puede llevar parámetros PM. 2. POO 26
  • 62.
    Constructor ‣ Sería elmiembro público cuyo nombre es el mismo que el de la clase, sin devolver nada, ni void ‣ Puede llevar parámetros ‣ Puede haber varios con distintas signaturas PM. 2. POO 26
  • 63.
    Ejemplo: complejo.h class CComplejo { constructor automático public: CComplejo(int re=0, int im=1) interfaz de uso void print() const; // no modif. objeto void pon(const int re=0, const int im=1); private: int real, imag; atributos }; CComplejo c1(3,2), c2; PM. 2. POO 27
  • 64.
    Constructor, casos Ejemplos deuso de Constructor Según encajen pueden ser llamados un constructor u otro. CComplejo c(10, -2), c2(5,4), c3[8]; al no poderse poner valores para cada elemento debe haber un constructor sin parámetros con valores por defecto PM. 2. POO 28
  • 65.
    Ejemplo: prucomp.cpp #include <iostream.h> #include"complejo.h" llamada implícita a constructor int main() { del objeto CComplejo c1; c1.print(); cout << endl; c1.pon(2,-3); c1.print(); cout << endl; } PM. 2. POO 29
  • 66.
    Construcción por copiade objetos • Constructor por copia – Sería el miembro público cuyo nombre es el mismo que el de la clase y cuyo único argumento es un objeto de la clase en modo const clase& CComplejo sin(3,2); CComplejo sin(con); // actua constructor por copia • No siempre hace falta. PM. 2. POO 30
  • 67.
    Construcción por copiade objetos La construcción por copia se "ejecuta" con la declaración: • explícita en la creación: CMatriz m2 = m1; • implícita en la creación: CMatriz m3(m1); PM. 2. POO 31
  • 68.
    Copia errónea deobjetos La iniciación de objetos durante la construcción admite pues diversas formas: class T { public: T(); // Creador sin parámetros T(tipo uno); // Creador con un parámetro T(const T& de); // constructor por copia… PERO SI NO HAY UN OPERADOR DE COPIA, EN GENERAL: ... t1 = t2; ... YA QUE hará sólo la copia de los atributos y no se hará la construcción de la estructura correcta de una nueva copia. PM. 2. POO 32
  • 69.
    Copia errónea deobjetos La iniciación de objetos durante la construcción admite pues diversas formas: class T { public: T(); // Creador sin parámetros T(tipo uno); // Creador con un parámetro T(const T& de); // constructor por copia… PERO SI NO HAY UN OPERADOR DE COPIA, EN GENERAL: ... t1 = t2; ERROR ... YA QUE hará sólo la copia de los atributos y no se hará la construcción de la estructura correcta de una nueva copia. PM. 2. POO 32
  • 70.
    Ejemplo: matriz.h class Matriz{ public: Matriz(int n, int m); constructor Matriz(const Matriz& origen); constructor por copia ~Matriz(void); int ver(const int fila,const int col); void pon(const int fila,const int col,const int x); void dims(int &n, int &m) {n=N;m=M;}; private: int N, M; int *datos; }; PM. 2. POO 33
  • 71.
    Métodos destructor PM. 2. POO 34
  • 72.
  • 73.
    Métodos destructor • Destructor – Miembro público cuyo nombre es el mismo que el de la clase con un ~ delante PM. 2. POO 34
  • 74.
    Métodos destructor • Destructor – Miembro público cuyo nombre es el mismo que el de la clase con un ~ delante – No devolver nada, ni void PM. 2. POO 34
  • 75.
    Métodos destructor • Destructor – Miembro público cuyo nombre es el mismo que el de la clase con un ~ delante – No devolver nada, ni void – No parámetros PM. 2. POO 34
  • 76.
    Métodos destructor • Destructor – Miembro público cuyo nombre es el mismo que el de la clase con un ~ delante – No devolver nada, ni void – No parámetros PM. 2. POO 34
  • 77.
    Métodos destructor • Destructor – Miembro público cuyo nombre es el mismo que el de la clase con un ~ delante – No devolver nada, ni void – No parámetros PM. 2. POO 34
  • 78.
    Destrucción implícita La destrucciónimplícita se llama sola, automáticamente, cuando el objeto deja de estar accesible, por ejemplo, al acabar el ámbito de su visibilidad La destrucción puede llamarse explícitamente llamando al método de destrucción aunque esto último suele ser innecesario PM. 2. POO 35
  • 79.
    Peligro de lacopia de parámetros Peor ocurre aún, si hacemos una llamada a una función externa como: ... pinta(t1); ... siendo void pinta(const T t1) los resultados serán igualmente desastrosos. ¿Por qué? PM. 2. POO 36
  • 80.
    Peligro de lacopia de parámetros El motivo es que pinta(t1) construye una copia (mal) de t1 para el parámetro local de pinta y al acabar pinta() destruye esa copia destruyendo de camino el original. Una solución es hacer void pinta(const T& t) • sea, declarar el parámetro como referencia constante – No se copia – No se cambia PM. 2. POO 37
  • 81.
    Peligro de lacopia de parámetros Al recibirse el objeto por referencia no hay destrucción automática al acabar el procedimiento y no habrá sorpresas en los casos de memoria dinámica enlazada como veremos. void pinta(const T& t) PM. 2. POO 38
  • 82.
    Operador de asignación= Pero el problema de la copia es más general: sólo hemos visto como evitarlo durante la creación por copia y durante el paso de parámetros. Para que la operación = funcione correctamente con nuestros objetos particulares hará falta sobrecargar el operador asignación con nuestro algoritmo particular de copiado. T& operator= (const T& orig); PM. 2. POO 39
  • 83.
    Copia por asignaciónde objetos en general ejemplo: class T { public: T(); // Creador sin parámetros T(tipo uno); // Creador con un parámetro T(const T& de); // constructor por copia T& operator= (const T& de); // operador de copia .... PM. 2. POO 40
  • 84.
    Las relaciones entreclasses A veces es conveniente que otra clase pueda ver mi parte privada cuando se quiere delegar una operación común a otra clase que necesitaría ver nuestra parte privada para hacerla PM. 2. POO 41
  • 85.
    AMISTAD entre clases ¿Puede ser posible que otra clase acceda a nuestra parte privada? PM. 2. POO 42
  • 86.
    AMISTAD entre clases ¿Puede ser posible que otra clase acceda a nuestra parte privada? Sí PM. 2. POO 42
  • 87.
    amistad entre clases permiso garantizado PM. 2. POO 43
  • 88.
    amistad entre clases permiso garantizado class Una { class Otra { friend class Otra; void metodo2(Una u) { private: u.atri = 33; int atri; u.metodo(); void metodo(); } }; }; PM. 2. POO 43
  • 89.
    Sobrecarga de << Sise define la clase ostream que tiene el operador a << como amiga friend ostream& operator<<(ostream &os, const Text& orig); y se desarrolla como por ejemplo: ostream& operator<<(ostream &os, const Text& orig) { os << orig.s; // accede a su parte privada return os; } PM. 2. POO 44
  • 90.
    class Text { public: uso: Text(const char* txtPtr); Text() : s(0) {}; ~Text(); Text(const Text& orig); bool operator== (const Text& derecho) const; t1 == t2 Ejemplo +completo char operator[ ] (unsigned long indice) const; t1[33] unsigned long Longitud() const; void pinta(const bool nl = true) const; friend Text operator+ (const Text& ls, const Text& rs); t3 = t1 + t2 operator const char*() const; (char*) (t2) Text& operator= (const Text& orig); t1 = t2 Text& operator= (const char *str); t1 = "abc" cout << t1; friend ostream& operator<<(ostream &os, const Text& orig); private: char *s; // la cadena C unsigned long l; unsigned long strlen(const char *str) const; void strasigna(const char *desde); bool strcmp(const char *con) const; }; 45
  • 91.
    #include <iostream.h> bool Text::operator== (const Text& derecho) const { #include "text.h" if (derecho.l == 0 && 0 == l) return true; // Constructor desde cadena C else Ejemplo +completo Text::Text(const char* txtPtr) : s(0), return strcmp(derecho.s); l(0) { } if (txtPtr != 0) char Text::operator[] (unsigned long indice) const { strasigna(txtPtr); if (0 <= indice && indice < l) } return s[indice]; // Constructor de copia else Text::Text(const Text& orig) : s(0), return '0'; l(orig.l) { } if (orig.l != 0) // averigua la longitud unsigned long Text::Longitud() const { strasigna(orig.s); return l; } } // destructor // Adapta el tipo (cast) a cadena C Text::~Text() { Text::operator const char*() const { delete[] s; return s; } } 46
  • 92.
    // Operador deasignación unsigned long Text::strlen(const char *str) Text& Text::operator= (const Text& orig) const { { unsigned long n = 0; // evita a = a; while (str[n]) if (this == &orig) n++; Ejemplo +completo return *this; return n; if (l != 0) { } delete[] s; void Text::strasigna(const char *desde) { l = 0; unsigned long i = 0; l = strlen(desde); } s = new char[l+1]; if (orig.l) while (s[i] = desde[i]) strasigna(orig.s); i++; return *this; } } bool Text::strcmp(const char *con) const // Operador de asignación desde una str { Text& Text::operator= (const char *str) { unsigned long i = 0; if (l != 0) { while (s[i] && con[i] && s[i] == con[i]) delete[] s; i++; l = 0; return s[i] == '0' && con[i] == '0'; } } if (str != 0) strasigna(str); return *this; } 47
  • 93.
    // amigo quepermite sobrecargar '+' para concatenar Texts Text operator+ (const Text& ls, const Text& rs) { Text ret; unsigned long i=0, ii=0; Ejemplo +completo ret.l = ls.l + rs.l; ret.s = new char[ret.l+1]; ret.s[0] = '0'; if (ls.s != NULL) { while (ret.s[i] = ls.s[i]) i++; ii = i-1; i = 0; } if (rs.s != NULL) while (ret.s[ii] = rs.s[i]) i++; ii++; return ret; } ostream& operator<<(ostream &os, const Text& orig) { 48
  • 94.
    espacios de nombres Unadeclaración accesible en todo el programa es una declaración global. La colección de todas las declaraciones se denomina espacio de nombres global. PM. 2. POO 49
  • 95.
    using namespace C++, sinembargo, proporciona a los programadores la posibilidad de situar las declaraciones en espacios de nombres definidos por el programa. namespace nombre { void f() { cout << desde f en nombre<<endl; }; la llamada hay que hacerla: nombre::f(); excepto que se ponga antes: using namespace nombre; PM. 2. POO 50
  • 96.
    librerías con namespace Lascabeceras que utilizan el espacio de nombres global suelen acabarse como clásicamente: .h Las librerías que sitúan sus declaraciones dentro de espacios de nombres (no globales) no usan extensión. Por ejemplo: <iostream> es un archivo de cabecera cuyas declaraciones están en el espacio de nombres std PM. 2. POO 51
  • 97.
    librerías con namespace Poreso hacemos: #include <iostream> #include <iomanip> using namespace std; int main () { cout << setw (10); cout << 77 << endl; return 0; } PM. 2. POO 52
  • 98.
    Miembros estáticos PM. 2. POO 53
  • 99.
    Miembros estáticos Se puedendefinir miembros (atributos o métodos) con el atributo static: PM. 2. POO 53
  • 100.
    Miembros estáticos Se puedendefinir miembros (atributos o métodos) con el atributo static: • Tal miembro es común a todos los objetos de tal clase. PM. 2. POO 53
  • 101.
    Miembros estáticos Se puedendefinir miembros (atributos o métodos) con el atributo static: • Tal miembro es común a todos los objetos de tal clase. • Tales miembros existen aunque no haya ningún objeto de tal clase PM. 2. POO 53
  • 102.
    Miembros estáticos Se puedendefinir miembros (atributos o métodos) con el atributo static: • Tal miembro es común a todos los objetos de tal clase. • Tales miembros existen aunque no haya ningún objeto de tal clase • Para usarlos se puede usar un objeto cualquiera de los de la clase o usar el especificador de ámbito Clase::cuenta = 33; PM. 2. POO 53
  • 103.
    Miembros estáticos Se puedendefinir miembros (atributos o métodos) con el atributo static: • Tal miembro es común a todos los objetos de tal clase. • Tales miembros existen aunque no haya ningún objeto de tal clase • Para usarlos se puede usar un objeto cualquiera de los de la clase o usar el especificador de ámbito Clase::cuenta = 33; • Pueden servir, por ejemplo, para mantener información global, como la cuenta de todos los objetos. No son datos globales, ya que mantienen los criterios de visibilidad. PM. 2. POO 53
  • 104.
  • 105.
    1 #include <iostream> 2 #include <string> 3 using namespace std; Ejemplo uso 5 int main(int argc, char *argv[]) { 6 string s = "Juan"; string 7 cout << s << endl; 8 cout << s + " Falgueras" << endl; 9 s += " (fin)"; 10 cout << s << endl; 11 cout << s.empty() << endl; 12 cout << s.length() << endl; 13 cout << s.max_size() << endl; 14 cout << s.append(" adiós") << endl; 15 cout << s.find("fin", 2) << endl; 16 cout << "En 6: " << s.at(6) << endl; 17 cout << "En 6: " << s[6] << endl; 18 cout << s.replace(6, 3, "hola") << endl; 19 cout << s.insert(10, " y adiós") << endl; 20 cout << s.erase(10, 4) << endl; 21 cout << s.substr(6, 9) << endl; 22 int i=0; 23 for(string::const_iterator it = s.begin(); it != s.end(); it++) 24 cout << i++ << " " << *it << endl; 25 getline(cin, s); 26 cout << s << endl; 27 return 0; 28 } 55
  • 106.
    Características especiales dela POO en C++ PM. 2. POO 56
  • 107.
    Características especiales dela POO en C++ Respecto a la POO, las características más importantes de C++ son: PM. 2. POO 56
  • 108.
    Características especiales dela POO en C++ Respecto a la POO, las características más importantes de C++ son: PM. 2. POO 56
  • 109.
    Características especiales dela POO en C++ Respecto a la POO, las características más importantes de C++ son: • Herencia múltiple PM. 2. POO 56
  • 110.
    Características especiales dela POO en C++ Respecto a la POO, las características más importantes de C++ son: • Herencia múltiple • Sobrecarga de operadores y funciones PM. 2. POO 56
  • 111.
    Características especiales dela POO en C++ Respecto a la POO, las características más importantes de C++ son: • Herencia múltiple • Sobrecarga de operadores y funciones • Derivación PM. 2. POO 56
  • 112.
    Características especiales dela POO en C++ Respecto a la POO, las características más importantes de C++ son: • Herencia múltiple • Sobrecarga de operadores y funciones • Derivación • Funciones virtuales PM. 2. POO 56
  • 113.
    Características especiales dela POO en C++ Respecto a la POO, las características más importantes de C++ son: • Herencia múltiple • Sobrecarga de operadores y funciones • Derivación • Funciones virtuales • Plantillas PM. 2. POO 56
  • 114.
    Características especiales dela POO en C++ Respecto a la POO, las características más importantes de C++ son: • Herencia múltiple • Sobrecarga de operadores y funciones • Derivación • Funciones virtuales • Plantillas • Gestión de excepciones. PM. 2. POO 56
  • 115.
    Diferencias C-C++ Se puedensobrecargar las funciones void swap(int& a, int& b); void swap(char& a, char& b); void swap(int& a, int& b, bool& nose); bool swap(int& a, char& b); todas son homónimas pero el compilador sabe en cada llamada a quién llamar por el tipo de argumentos que se le pongan PM. 2. POO 57
  • 116.
    Valores por defecto Argumentoscon valor por defecto leehasta(char s[], int MAX, char delim = ‘n’) int a(int c, int a=1, int b=2) hace que a(1), ó a(1,2) ó a(1,2,3) no sean ambiguos pero int a(int a=1, int b=2, int c) NO al final a(4,5) ?? NOTA: También se pueden dar ambigüedades si se ponen valores por defecto a funciones sobrecargadas PM. 2. POO 58
  • 117.
    Pequeñas diferencias C-C++(2) Funciones inline frente a macros de preprocesador supongamos definido #define cuadrado(x) (x*x) entonces void f(double d, int i) { r = cuadrado(d); // va bien r = cuadrado(i++); // va mal: significa (i++*i++); r = cuadrado(d+1); // va mal: significa (d+1*d+1); // = (d+d+1); iría mejor, aunque no siempre bien: #define cuadrado(x) ((x)*(x)) PM. 2. POO 59
  • 118.
    Pequeñas difs. C-C++:funciones inline sigue sin resolver cuadrado(i++) Así que C++ aporta una solución: inline int icuadrado(int x) { return x * x; } que expande C++ (no el procesador), sí resuelve el problema: icuadrado(i++) // va bien ya que es el propio parser de C++ el que interpreta el código PM. 2. POO 60
  • 119.
    Pequeñas difs. C-C++:funciones inline • La ventaja de las funciones inline es que no hay retraso con llamadas a función. • Son expresiones que se repiten en el código cada vez que se usan sin llamar (más lento) a una función • A cambio generan un código más largo es como una función normal pero que se expande entre las líneas del código que la llama PM. 2. POO 61
  • 120.
  • 121.