martes, 26 de enero de 2016

EL POLIMORFISMO

http://cpp.sh/
En programación orientada a objetos, el polimorfismo se refiere a la propiedad por la que es posible enviar mensajes sintácticamente iguales a objetos de tipos distintos. El único requisito que deben cumplir los objetos que se utilizan de manera polimórfica es saber responder al mensaje que se les envía.
La apariencia del código puede ser muy diferente dependiendo del lenguaje que se utilice, más allá de las obvias diferencias sintácticas.
Por ejemplo, en un lenguaje de programación que cuenta con un sistema de tipos dinámico (en los que las variables pueden contener datos de cualquier tipo u objetos de cualquier clase) como Smalltalk no se requiere que los objetos que se utilizan de modo polimórfico sean parte de una jerarquía de clases.
En el siguiente ejemplo hacemos uso del lenguaje C++ para ilustrar el polimorfismo. Se observa a la vez el uso de las funciones virtuales puras, como se les conoce en C++, estas funciones constituyen una interfaz más consistente cuando se trabaja con una jerarquía de clases, puesto que hacen posible el enlace durante la ejecución. Sin embargo como se verá, para que el polimorfismo funcione no es una condición obligatoria que todas las funciones en la clase base sean declaradas como virtuales.

Diagrama de clases UML, que describe gráficamente la relación entre la clase base Figura y sus posibles clases derivadas, y la entidad que utiliza esta estructura: la Aplicación, también identificado como objeto Cliente.
#include<iostream>
using namespace std;

class Figura {
  private:
  float base;
  float altura; 
  public:
 void captura();
 virtual unsigned float perimetro()=0;
 virtual unsigned float area()=0;
};

class Rectangulo: public Figura { 
 public:
  void imprime();
  unsigned float perimetro(){return 2*(base+altura);}
  unsigned float area(){return base*altura;}
};

class Triangulo: public Figura {
 public:
  void muestra();
  unsigned float perimetro(){return 2*altura+base}
  unsigned float area(){return (base*altura)/2;}
};

void Figura::captura()
{
 cout << "CALCULO DEL AREA Y PERIMETRO DE UN TRIANGULO ISÓSCELES Y UN RECTANGULO:" << endl;
 cout << "escribe la altura: ";
 cin >> altura;
 cout << "escribe la base: ";
 cin >> base;
 cout << "EL PERIMETRO ES: " << perimetro();
 cout << "EL AREA ES: " << area();
getchar();
return 0;
}

Polimorfismo desde una interfaz[

Aunque el polimorfismo es el mismo se aplique donde se aplique, el modo en que se aplica desde una interfaz puede resultar un poco más oscuro y difícil de entender. Se expone un sencillo ejemplo (en VB-NET) comentado para entender como funciona aplicado desde una interfaz, primero se escribe el código y luego se comenta el funcionamiento. Nota: para no enturbiar el código en exceso, todo lo que no se declara privado se sobreentiende público.
 ' Declaramos una interfaz llamada IOperar y declaramos una función llamada Operar 
  ' que implementarán las clases deseadas:
 Interface IOperar
 Function Operar(valor1 as integer, valor2 as integer) as long
 End Interface
 
  ' Declaramos una clase que trabaja más alejada del usuario y que contendría funciones comunes
  ' para las siguiente clase, si no fueran idénticas irían en la interfaz, 
  ' pero al caso de mostrar el polimorfismo se suponen idénticas:
  Class Operacion
  Function Calcular(clasellamante as Object) as Long 
  ' aquí iría el código común a todas las operaciones.... que llaman a esa función
  ' por ejemplo recoger los 2 valores de la operación, chequear que están en el rango deseado, etc.

  ' se supone que la función inputValor recoge un valor de algún sitio
  valor1 as integer = inputValor() 
  valor2 as integer = inputValor()
 
  op as New IOperar = clasellamante
  Return op.Operar(valor1,valor2) 'AQUÍ es donde se utiliza el polimorfismo.
  End Function
  End Class
  ' Declaramos 2 clases: Sumar y Restar que implementan la interfaz y que llaman a la clase Operacion:
  Class Sumar
  Implements IOperar
  Private Function Operar(valor1 as Integer, valor2 as Integer) as Long Implements IOperar.Operar
  Return valor1 + valor2
  End Function
 
  Function Calcular() as Long
  op as New operacion
  Return op.Calcular(Me) ' se está llamando a la función 'Calcular' de la clase 'Operación'
  End Function
  End Class
  ' segunda clase....
  Class Restar
  Implements IOperar
  Private Function Operar(valor1 as Integer, valor2 as Integer) as Long Implements IOperar.Operar
  Return valor1 - valor2
  End Function
 
  Function Calcular() as Long
  op as New operacion
  Return op.Calcular(Me) ' se está llamando a la función 'Calcular' de la clase 'Operación'
  End Function
  End Class
 La interfaz expone un método que puede ser implementado por las diferentes clases, normalmente relacionadas entre si. Las clases Sumar y Restar implementan la interfaz pero el método de la interfaz lo declaramos privado para evitar ser accedido libremente y además tienen un método llamado Calcularque llama a la clase Operación donde tenemos otro método con el mismo nombre. Es esta clase última la que realiza el polimorfismo y debe fijarse como es a través de una instancia de la interfaz que llama al método operar. La interfaz sabe a qué método de qué clase llamar desde el momento que asignamos un valor a la variable OP en el método Calcular de la clase Operación, que a su vez recibió la referencia del método Calcular desde la clase que la llama, sea ésta cual sea, se identifica a sí misma, mediante la referencia Me ó This según el lenguaje empleado. Debe notarse que la instancia de la interfaz accede a sus métodos aunque en sus clases se hayan declarado privadas.

PARA VER EL FUNCIONAMIENTO DEL PROGRAMA DE EJEMPLO, DIRIGIRSE A ESTE ENLACE DONDE COPIE Y PEGUE EL EJEMPLO .

SOBRECARGA DE OPERADORES DE C++

La sobrecarga de operadores es uno de los mecanismos que nos permite ampliar las capacidades de los lenguajes de programación orientados a objetos. En C++, la declaración y definición de una sobrecarga de operador es muy similar a la declaración y definición de una función cualquiera. El ejemplo más sencillo de una sobrecarga de operadores nos lo da el lenguaje mismo, es decir, en una operación aritmética (por ejemplo, una suma ) el compilador determina el tipo de operación requerida de acuerdo con el tipo de datos involucrados. Vamos a suponer que se tienen las variables: int A, B; double X, Yint R; y las siguientes instrucciones:
R = A + B - C;
R = A + X;
R = X + Y;
Ahora bien:
  • en el primer caso el compilador determina que el tipo de operación requerida es una suma de enteros debido a que los dos miembros ( A y B ) de la suma son del tipo entero.
  • en el segundo caso parece ser que las cosas no son tan claras, ya que en este los miembros involucrados en la suma son de tipos diferentes, sin embargo el compilador determinará el tipo de operación requerida y depositará en el resultado ( R )el valor resultante redondeado.
  • en el tercero y último de los casos el compilador determina que el tipo de operación requerida es una suma de reales debido a que los dos miembros ( X e Y ) de la suma son del tipo double. También en este caso el resultado de la suma se redondea antes de ponerlo en R.

Mi primer sobrecarga

Para poner un ejemplo práctico de sobrecarga del operador de suma ( + ) vamos a considerar el caso de la clase pareja mostrada en seguida:
class Pareja {
public:
    double a, b;

    // constructor parametrizado
    Pareja(const double a,const double b)
    {
        this->a = a;
        this->b = b;
    }
};

int main()
{
    Pareja A(50, 75 );
    Pareja B(150, 175 );
    Pareja C = A + B;

    return 0;
}
Si usted trata de compilar el programa anterior descubrirá que el compilador se queja, es decir, el compilador no sabe que hacer en el caso de la instrucción Pareja C = A + B; aunque es evidente que se trata de la declaracion del objeto C y que el mismo se espera que sea igual a la suma de los objetos A y B. El error se debe al hecho de que el tipo Pareja es en realidad una clase y no un tipo primitivo y, en consecuencia, se debe de adiestrar al mismo compilador para que éste sepa de que manera hara la suma de dos objetos del tipo Pareja. Así, para solucionar el error vamos a sobrecargar el operador + para trabajar la suma de dos de dichos objetos. Vamos:
// Titulo..: programa sobrecarga01.cpp
// Objetivo: demostración de sobrecarga de operadores
// Autor...: Oscar E. Palacios
#include <iostream>
using namespace std;

class Pareja {
public:
    double a, b;

    // constructor parametrizado
    Pareja(const double a,const double b)
    {
        this->a = a;
        this->b = b;
    }
};

// Sobrecarga del operador +
Pareja& operator +(const Pareja &p1,const Pareja &p2)
{
  return *(new Pareja(p1.a + p2.a, p1.b + p2.b) );
}

int main()
{
    Pareja A(50, 75 );
    Pareja B(150, 175 );
    Pareja C = A + B;

    cout << "A = " << A.a << ',' << A.b << "\n";
    cout << "B = " << B.a << ',' << B.b << "\n";
    cout << "C = " << C.a << ',' << C.b << "\n";

    return 0;
}

Sintaxis general

Tal y como usted lo habrá notado, la declaración de sobrecarga en el programa anterior es lo más parecido a una función, es decir, la sintaxis general para sobrecargar uno operador cualquiera es:



  1. tipo se refiere al tipo regresado por el operador
  2. operator es una palabra reservada y debe aparecer en toda declaración de sobrecarga de operadores
  3. el simbolo + está en representación de cualquier operador
  4. lista de parámetros indica los argumentos sobre los que operarará la función de sobrecarga
Nota: en el caso de que el operador sobrecargado se hace para una clase específica la sintaxis se extiende de la siguiente manera:nombre_clase::operator + (lista de parámetros);
Regresando al caso de la clase Pareja, específicamente al operador + de sobrecarga para dicha clase, nos damos cuenta que dicho operador opera sobre dos objetos de dicha clase y también devuelve un resultado de la misma clase. Esto es lo más recomendable ya que si usted recuerda el compilador regresa un resultado entero si es que (por ejemplo) se le da una instrucción como: R = 100 + 23;. En todo caso, el resultado devuelto por los operadores sobrecargados es responsabilidad del que esta programando
EJEMPLO DE PROGRAMA:
#include <iostream>
using namespace std;
 
class Tiempo {
  public:
   Tiempo(int h=0, int m=0) : hora(h), minuto(m) {}
   
   void Mostrar();
   Tiempo operator+(Tiempo h);
       
  private:
   int hora;
   int minuto;
};

Tiempo Tiempo::operator+(Tiempo h) {
   Tiempo temp;
   
   temp.minuto = minuto + h.minuto;
   temp.hora   = hora   + h.hora;
   
   if(temp.minuto >= 60) {
      temp.minuto -= 60;
      temp.hora++;
   }
   return temp;
}

void Tiempo::Mostrar() {
   cout << hora << ":" << minuto << endl;
}

int main() {
   Tiempo Ahora(12,24), T1(4,45);
   
   T1 = Ahora + T1;   // (1)
   T1.Mostrar();
   
   (Ahora + Tiempo(4,45)).Mostrar(); // (2)
   
   return 0;
}

PARA VER EL FUNCIONAMIENTO DEL PROGRAMA DE EJEMPLO, DIRIGIRSE A ESTE ENLACE DONDE COPIE Y PEGUE EL EJEMPLO .

  • http://cpp.sh/




FUENTE DE CONSULTA:
  • https://es.wikibooks.org/wiki/Programaci%C3%B3n_en_C%2B%2B/Sobrecarga_de_Operadores
  • http://www.chuidiang.com/clinux/sobrecarga/sobrecarga.php
  • http://c.conclase.net/curso/?cap=035




CONSTRUCTORES DE C++

Constructores y destructores de c ++

1.  Constructores
^
Los constructores son funciones miembro especiales que sirven para inicializar un objeto de una determinada clase al mismo tiempo que se declara.
Los constructores son especiales por varios motivos:
·         Tienen el mismo nombre que la clase a la que pertenecen.
·         No tienen tipo de retorno, y por lo tanto no retornan ningún valor.
·         No pueden ser heredados.
·         Por último, deben ser públicos, no tendría ningún sentido declarar un constructor como privado, ya que siempre se usan desde el exterior de la clase, ni tampoco como protegido, ya que no puede ser heredado.
Sintaxis:
class <identificador de clase> {
    public:
        <identificador de clase>(<lista de parámetros>) [: <lista de constructores>] {
            <código del constructor>
        }
        ...
}

Añadamos un constructor a nuestra clase pareja:
#include <iostream>
using namespace std;

class pareja {
   public:
      // Constructor
      pareja(int a2, int b2);
      // Funciones miembro de la clase "pareja"
      void Lee(int &a2, int &b2);
      void Guarda(int a2, int b2);
   private:
      // Datos miembro de la clase "pareja"
      int a, b;
};

pareja::pareja(int a2, int b2) {
   a = a2;

2.  Destructores
Los destructores son funciones miembro especiales que sirven para eliminar un objeto de una determinada clase. El destructor realizará procesos necesarios cuando un objeto termine su ámbito temporal, por ejemplo liberando la memoria dinámica utilizada por dicho objeto o liberando recursos usados, como ficheros, dispositivos, etc.
Al igual que los constructores, los destructores también tienen algunas características especiales:
·         También tienen el mismo nombre que la clase a la que pertenecen, pero tienen el símbolo ˜ delante.
·         No tienen tipo de retorno, y por lo tanto no retornan ningún valor.
·         No tienen parámetros.
·         No pueden ser heredados.
·         Deben ser públicos, no tendría ningún sentido declarar un destructor como privado, ya que siempre se usan desde el exterior de la clase, ni tampoco como protegido, ya que no puede ser heredado.
·         No pueden ser sobrecargados, lo cual es lógico, puesto que no tienen valor de retorno ni parámetros, no hay posibilidad de sobrecarga.
Cuando se define un destructor para una clase, éste es llamado automáticamente cuando se abandona el ámbito en el que fue definido. Esto es así salvo cuando el objeto fue creado dinámicamente con el operador new, ya que en ese caso, cuando es necesario eliminarlo, hay que hacerlo explícitamente usando el operador delete.
En general, será necesario definir un destructor cuando nuestra clase tenga datos miembro de tipo puntero, aunque esto no es una regla estricta.
Ejemplo:
#include <iostream>
#include <cstring>
using namespace std;

class cadena {
  public:
   cadena();        // Constructor por defecto
   cadena(const char *c); // Constructor desde cadena c
   cadena(int n);   // Constructor de cadena de n caracteres
   cadena(const cadena &);   // Constructor copia
   ~cadena();       // Destructor

   void Asignar(const char *dest);
   char *Leer(char *c);
  private:
   char *cad;       // Puntero a char: cadena de caracteres
};


PARA VER EL FUNCIONAMIENTO DEL PROGRAMA DE EJEMPLO, DIRIGIRSE A ESTE ENLACE DONDE COPIE Y PEGUE EL EJEMPLO .

  • http://cpp.sh/



3.  Conclusiones:
·         Ayudan al objeto y estos mismos son tipo parte dentro de la estructura.
·         Los dos no tienen un tipo de retorno por lo cual no retornan ningún valor.
·         Deben ser públicos para que se lo pueda utilizar en el exterior del programa y no tenga dificultades.
4.  Bibliografía:


LA HERENCIA EN C++


Una de las principales propiedades de las clases es la herencia. Esta propiedad nos permite crear nuevas clases a partir de clases existentes, conservando las propiedades de la clase original y añadiendo otras nuevas.

Cada nueva clase obtenida mediante herencia se conoce como clase derivada, y las clases a partir de las cuales se deriva, clases base. Además, cada clase derivada puede usarse como clase base para obtener una nueva clase derivada. Y cada clase derivada puede serlo de una o más clases base. En este último caso hablaremos de derivación múltiple.
Esto nos permite crear una jerarquía de clases tan compleja como sea necesario.
Bien, pero ¿que ventajas tiene derivar clases?
En realidad, ese es el principio de la programación orientada a objetos. Esta propiedad nos permite encapsular diferentes partes de cualquier objeto real o imaginario, y vincularlo con objetos más elaborados del mismo tipo básico, que heredarán todas sus características. Lo veremos mejor con un ejemplo.
Un ejemplo muy socorrido es de las personas. Supongamos que nuestra clase base para clasificar a las personas en función de su profesión sea "Persona". Presta especial atención a la palabra "clasificar", es el punto de partida para buscar la solución de cualquier problema que se pretenda resolver usando POO. Lo primero que debemos hacer es buscar categorías, propiedades comunes y distintas que nos permitan clasificar los objetos, y crear lo que después serán las clases de nuestro programa. Es muy importante dedicar el tiempo y atención necesarios a esta tarea, de ello dependerá la flexibilidad, reutilización y eficacia de nuestro programa.
Ten en cuenta que las jerarquías de clases se usan especialmente en la resolución de problemas complejos, es difícil que tengas que recurrir a ellas para resolver problemas sencillos.
Siguiendo con el ejemplo, partiremos de la clase "Persona". Independientemente de la profesión, todas las personas tienen propiedades comunes, nombre, fecha de nacimiento, género, estado civil, etc.
Jerarquía de clases para Persona
La siguiente clasificación debe ser menos general, supongamos que dividimos a todas las personas en dos grandes clases: empleados y estudiantes. (Dejaremos de lado, de momento, a los estudiantes que además trabajan). Lo importante es decidir qué propiedades que no hemos incluido en la clase "Persona" son exclusivas de los empleados y de los estudiantes. Por ejemplo, los ingresos por nómina son exclusivos de los empleados, la nota media del curso, es exclusiva de los estudiantes. Una vez hecho eso crearemos dos clases derivadas de Persona: "Empleado" y "Estudiante".

EJEMPLO DE HERENCIA:

#include <iostream>
using namespace std;

class base {

 int i, j;

public:
 void set(int a, int b) { i = a; j = b; }
 void mostrar() { cout << i << " " << j << "\n"; }
};

class derivada : public base {

 int k;

public:
 derivada(int x) { k = x; }
 void mostrar_k() { cout << k << "\n"; }
};

int main()
{
 derivada obj(3);
 
 obj.set(1, 2); // accesar a miembro de base
 obj.mostrar(); // accesar a miembro de base

 obj.mostrar_k(); // usa miembro de la clase derivada

return 0;
}




PARA VER EL FUNCIONAMIENTO DEL PROGRAMA DE EJEMPLO, DIRIGIRSE A ESTE ENLACE DONDE COPIE Y PEGUE EL EJEMPLO .

  • http://cpp.sh/






FUENTE DE CONSULTA:
  • https://es.wikibooks.org/wiki/Programaci%C3%B3n_en_C%2B%2B/Herencia
  • http://c.conclase.net/curso/?cap=036