Gabriel Viganotti | 2 May 2008 11:58
Picon

Re: Herencias en C++: 2/3

Hola Dani,

muy lindo, me gusto. Solo para asegurarme que no me estoy perdiendo ningun detalle (o que no me estoy perdiendo :-) ), el metodo entonces devuelve bool y no int verdad?



On Mon, Apr 14, 2008 at 5:18 PM, Daniel Gutson <danielgutson-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
Sigo con
  3) usos + avanzados: template design pattern & mixins, private inheritance, curiously recursive template pattern
 
=================================================================
Ya hubo un adelanto de 'private inheritance' (ejemplos de Soledad, politicos corruptos y demas).
 
Sigo con tres usos un cacho mas complejos de herencia en C++: template design pattern & mixins, CRTP, y un caso practico de este ultimo: aspect oriented programming.
 
a) Template Design Pattern.
 
 Este pattern intenta resolver lo siguiente: cuando existen varios 'sabores' de un algoritmo, pero todos tienen en comun la misma secuencia de pasos. Lo que varia, es la implementacion de uno o mas de esos pasos.
Por ejemplo: odenar tanto de > como de <, el algoritmo no cambia, lo que cambia es la implementacion de la comparacion.
 
Voy a mostrar esto como se hace de las dos maneras: usando polimorfismo por inclusion, y polimorfismo parametrico, con mi sorting favorito (el selection).
 
El pseudocodigo como todo mundo conoce:
      for i = 1 .. n-1
        j = mejor_del_rango(i, n);
        if  (i != j)
           swap v[i], v[j]
 
y mejor_del_rango selecciona, de acuerdo a algun criterio el mejor o el mayor del rango pedido. Esto va a denotar el 'sabor'.
 
Entonces, la idea del Template Design Pattern, es ubicar los pasos a la clase base, y dejar que una derivada implemente el 'sabor'.
Ej:
    class SelectionSort
    {
         public: void sort(vector<int>& v);
    private:
         virtual int comparar(int x, int y) const = 0;
    };
 
   class MenorAMayor: public SelectionSort
   {
        private: virtual int comparar(int x, int y) const { return x < y; }
   };
 
Esto es: la clase base hace de master, y la derivada de slave. Osea, la base tiene la manijita, y le pregunta a la derivada "que onda x e y?".
Asi las cosas, un usuario instancia un MenorAMayor por ejemplo, e invoca el metodo publico de la clase base: sort.
 
 
Pasando a la version parametrica:
 
template <class Comparador>
class SelectionSort
{
    void sort(vector<int>& vec, Comparador& c)
    {
          .... c.comparar(vec[i], vec[j]);
    }
};
 
Como se ve en este ultimo ejemplo, el polimorfismo esta dado en que, cualquier Comparador que se jacte de serlo, tiene que proveer un metodo comparar que reciba dos enteros, y devolver un bool. La clase SelectionSort sigue teniendo la manijita, y usa al Comparador para preguntarle qué onda.
Esto ultimo tambien se conoce como 'policy class' o 'traits' (en este caso, la clase Comparador es la policy class, o politica de comparacion).
 
Es muy importante en esto tener en claro los roles: quien hace de master y quien de slave.
 
Como me quedó el mail muy largo, dejo los otros temas para un "Herencias en C++: 2.1/3".
 
Solo comparo brevemente las dos versiones: polimorfismo por inclusion o parametrico.
Ventajas de la version x inclusion:
   * ejecutable mas chico
   * mas legible
   * errores de compilacion mas claros.
   * codigo mas ordenado (no requiere inlines, por lo que todo puede estar organizado en .cpp y .h)
 
Ventajas de la version parametrica:
  * mas performante en general. Habilita inlining.
 
 
PERO OJO: lo importante es que NO se mezclen los tipos de polimorfismo. Regla general: si usas 'virtual' y 'template' en la misma clase, tiene Oracle (oloráculo).
 
  Daniel.





--
Gabriel Viganotti
Cel: +44 7795491396

"Monday's problems are the result of Friday's fatigue"
--~--~---------~--~----~------------~-------~--~----~
¿Eres miembro de "CyC++ Buenos Aires" verdad? Si no lo eres, has recibido este mesaje por error.
En caso de duda visita "http://groups.google.com/group/cppba"
-~----------~----~----~----~------~----~------~--~---

Daniel Gutson | 2 May 2008 14:21
Picon

Re: Herencias en C++: 2/3

Ya casi ni me acordaba de esto.
Devuelve int para ser generico, y retornar con la logica de strcmp  (-1, 0, +1)


On Fri, May 2, 2008 at 6:58 AM, Gabriel Viganotti <gabrielviganotti-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
Hola Dani,

muy lindo, me gusto. Solo para asegurarme que no me estoy perdiendo ningun detalle (o que no me estoy perdiendo :-) ), el metodo entonces devuelve bool y no int verdad?



On Mon, Apr 14, 2008 at 5:18 PM, Daniel Gutson <danielgutson-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
Sigo con
  3) usos + avanzados: template design pattern & mixins, private inheritance, curiously recursive template pattern
 
=================================================================
Ya hubo un adelanto de 'private inheritance' (ejemplos de Soledad, politicos corruptos y demas).
 
Sigo con tres usos un cacho mas complejos de herencia en C++: template design pattern & mixins, CRTP, y un caso practico de este ultimo: aspect oriented programming.
 
a) Template Design Pattern.
 
 Este pattern intenta resolver lo siguiente: cuando existen varios 'sabores' de un algoritmo, pero todos tienen en comun la misma secuencia de pasos. Lo que varia, es la implementacion de uno o mas de esos pasos.
Por ejemplo: odenar tanto de > como de <, el algoritmo no cambia, lo que cambia es la implementacion de la comparacion.
 
Voy a mostrar esto como se hace de las dos maneras: usando polimorfismo por inclusion, y polimorfismo parametrico, con mi sorting favorito (el selection).
 
El pseudocodigo como todo mundo conoce:
      for i = 1 .. n-1
        j = mejor_del_rango(i, n);
        if  (i != j)
           swap v[i], v[j]
 
y mejor_del_rango selecciona, de acuerdo a algun criterio el mejor o el mayor del rango pedido. Esto va a denotar el 'sabor'.
 
Entonces, la idea del Template Design Pattern, es ubicar los pasos a la clase base, y dejar que una derivada implemente el 'sabor'.
Ej:
    class SelectionSort
    {
         public: void sort(vector<int>& v);
    private:
         virtual int comparar(int x, int y) const = 0;
    };
 
   class MenorAMayor: public SelectionSort
   {
        private: virtual int comparar(int x, int y) const { return x < y; }
   };
 
Esto es: la clase base hace de master, y la derivada de slave. Osea, la base tiene la manijita, y le pregunta a la derivada "que onda x e y?".
Asi las cosas, un usuario instancia un MenorAMayor por ejemplo, e invoca el metodo publico de la clase base: sort.
 
 
Pasando a la version parametrica:
 
template <class Comparador>
class SelectionSort
{
    void sort(vector<int>& vec, Comparador& c)
    {
          .... c.comparar(vec[i], vec[j]);
    }
};
 
Como se ve en este ultimo ejemplo, el polimorfismo esta dado en que, cualquier Comparador que se jacte de serlo, tiene que proveer un metodo comparar que reciba dos enteros, y devolver un bool. La clase SelectionSort sigue teniendo la manijita, y usa al Comparador para preguntarle qué onda.
Esto ultimo tambien se conoce como 'policy class' o 'traits' (en este caso, la clase Comparador es la policy class, o politica de comparacion).
 
Es muy importante en esto tener en claro los roles: quien hace de master y quien de slave.
 
Como me quedó el mail muy largo, dejo los otros temas para un "Herencias en C++: 2.1/3".
 
Solo comparo brevemente las dos versiones: polimorfismo por inclusion o parametrico.
Ventajas de la version x inclusion:
   * ejecutable mas chico
   * mas legible
   * errores de compilacion mas claros.
   * codigo mas ordenado (no requiere inlines, por lo que todo puede estar organizado en .cpp y .h)
 
Ventajas de la version parametrica:
  * mas performante en general. Habilita inlining.
 
 
PERO OJO: lo importante es que NO se mezclen los tipos de polimorfismo. Regla general: si usas 'virtual' y 'template' en la misma clase, tiene Oracle (oloráculo).
 
  Daniel.





--
Gabriel Viganotti
Cel: +44 7795491396

"Monday's problems are the result of Friday's fatigue"



--~--~---------~--~----~------------~-------~--~----~
¿Eres miembro de "CyC++ Buenos Aires" verdad? Si no lo eres, has recibido este mesaje por error.
En caso de duda visita "http://groups.google.com/group/cppba"
-~----------~----~----~----~------~----~------~--~---

Daniel Gutson | 2 May 2008 14:24
Picon

n-dispatching > SOLUCION PARTE 1

Me molestan las cosas sin terminar >:)

PROBLEMA:
   tengo una jerarquía de clases q todas derivan de class Base {...};
   tengo un Base* array[]; que por supuesto cada elemento serán distintas derivadas.
   y tengo varios procesos distintos (P1, P2, Pn), cada uno hace cosas distintas de acuerdo a la derivada que sea.

Solución?? Cómo diseñarían las clases de la jerarquía, y los procesos?
Constraint: agregar nuevas derivadas y nuevos procesos tiene que impactar lo menos posible, en lo posible no joder a lo que ya existe.

   Daniel.

--~--~---------~--~----~------------~-------~--~----~
¿Eres miembro de "CyC++ Buenos Aires" verdad? Si no lo eres, has recibido este mesaje por error.
En caso de duda visita "http://groups.google.com/group/cppba"
-~----------~----~----~----~------~----~------~--~---

Daniel Gutson | 2 May 2008 16:10
Picon

Re: herencias en C++: 1/3

PERDON,
  mirando atras los mails, a raiz del mail del Gaby, vi que me olvide de un tipo de herencia: la repetida (repeated inheritance).
 
struct Base { } ;

struct Der1 : Base {  };
struct Der2 : Base {  };

struct FinalDer : Der1, Der2 { };

Se llama herencia repetida, porque Base aparece mas de una vez, con todos sus datos repetidos. Lo que C++ no soporta (aun) es especificar overridings de una u otra. Hay laburo en eso.

 
   Daniel.

 
On 4/3/08, Daniel Gutson <danielgutson <at> gmail.com> wrote:
Sres,
  aca va algo de estas cosas. Si bien es un resumen, lo mando en varios 'capitulos' porque necesito laburar :)
 
Lo que voy a enviar es:
  1) tipos de herencia: simple multiple y virtual.
  2) usos basicos de herencia en C++: polimorfismo x inclusion, y reuso; observer design pattern.
  3) usos + avanzados: template design pattern & mixins, private inheritance, curiously recursive template pattern
  4) heredar versus contener; el problema del corazon; la paradoja de la elipse.
 
Dejo LSP para otro thread.
 
Empiezo con puntos 1 y 2 en este mail.
 
 
=================================================
1) Los tipos de herencia seguro los conocen: simple, multiple, y virtual (la tipo rombo):   [uso structs para no escribir los public]
 
   SIMPLE:      struct Base {}; struct Der : Base {};
 
   MULTIPLE:  struct Base1 {}; struct Base2 {}; struct Der : Base1, Base2 {};
 
   VIRTUAL:    struct Port {}; struct InputPort: virtual Port {}; struct OutputPort: virtual Port {}; struct USB : InputPort, OutputPort {};
          (se puede decir bastante de este tema, pero prefiero que si a alguien le interesa que profundice que me avise y abro otro thread; en este solo resumen)
 
2) los usos basicos de herencia son: para heredar interfaz (polimorfismo x inclusion), y para heredar comportamiento (reuso). La primera es GENERALMENTE publica (ver punto 3), la segunda es (tambien generalmente) protegida.
 
2.1: heredar para tener polimorfismo.
 
struct Interfaz
{
    virtual void saludar() = 0;
};
 
class Implementacion : public Interfaz
{
private:    // lo explicito por razones didacticas
    virtual void saludar() { cout << "chau mundo"; }
};
 
Al contrario de lo q mucha gente cree, el acceso a traves de la tabla virtual no le importa si es public, protected, private. De hecho, es una buena practica escribir las implementaciones de metodos de una interfaz en la parte privada de la clase implementadora. Mas aun, lo UNICO que una clase implementadora deberia exportar publicamente, es su constructor (ya que UNICAMENTE se debe acceder a traves de su/s interfaz/ces), lo cual tambien puede tomarse con pinzas gracias a los factory pattern (factory class, factory method, y builder).
 
2.2: heredar para reusar codigo
Las clases bases proveen funcionalidad; pueden no exportar nada publicamente, solo protegidamente. La relacion es: clase derivada hace de 'master', y la base de 'slave'. Es decir, el flujo se INICIA en la derivada, y ésta pide colaboración de la base como cosa suya; el usuario no se entera de esto. (comparar con el Template design pattern cuando hable de eso en otro mail: es exactamente opuesto).
Esto cobra sentido cuando hay muchas derivadas que tienen un laburo en comun, entonces se mueve a una clase base en comun y las derivadas lo usan.
 
class BaseComun
{   protected:
       int dato;
       void laburo_comun() { ....dato.... }
};
 
class Der1
{
   public: void metodo_publico() { ...laburo_comun()... }
};
 
class Der2: ....idem Der1 ...
 
 
2.3: el Observer design pattern.
Es un caso particular de 2.1 (herencia para polimorfismo). Tambien conocido como 'listener' en java. Reemplaza a los callbacks (punteros a funcion) de C.
Cuando hay dos modulos, relacionados como 'modulo A usa a modulo B', la comunicacion de A -> B es invocando funciones de la API de B. Pero que pasa cuando B le quiere avisar algo a A? Por ejemplo, el modulo B provee servicios de timers. Entonces, la API es 'disparar timer', pero B tiene que avisarle a A cuando el timer expira. Se suele hacer asi:
 
struct Timers_API       // este sería B
{
    struct Observer
    {   virtual void timeout() = 0; };
 
    void set_timer( int milliseconds, Observer* observer);
};
 
////////////////// mientras tanto, en otro lugar de Ciudad Código //////////////////////////////////
 
class Usuaria : private Timers_API::Observer
{
    void set_timer(Timers_API& timers_api)
    {    timers_api.set_timer( 10, this);
 
   virtual void timeout()        // callback
   {  cout << "time out!"; }
};
 
 
Bueno, paso a explicar esto y termino el mail:
   * la clase Timers_API provee una funcionalidad: settear un timer. Pero ademas, dice que: "cualquiera que pretenda usarme, debe proveerme alguien a quien avisarle cuando un timer termina". Como parte de este contrato, la API define una interfaz, la Observer. Ahi hay un metodo que se usa para que este modulo de timers le avise al usuario que un timer terminó.
   * la clase Usuaria, ademas de ser usuaria, decide (porque tiene ganas) recibir ella misma el aviso de timeout. Osea que tiene doble rol: settear el timer, y escuchar su expiración. Sigue las enseñanzas de El Padrino: <las malas noticias las quiero recibir personalmente>.
   * la herencia es privada (voy a explicar + en punto 3 cuando lo mande), porque a nadie de afuera le interesa saber que la clase usuaria quiere recibir las noticias de expiracion personalmente. Si yo invoco metodos de Usuaria, no me interesa saber si usa o no timers, mucho menos como maneje los timeouts.
 
 
Si algo no quedó claro de todo esto, xfav avisen y aclaro mas.
 
   Daniel.


--~--~---------~--~----~------------~-------~--~----~
¿Eres miembro de "CyC++ Buenos Aires" verdad? Si no lo eres, has recibido este mesaje por error.
En caso de duda visita "http://groups.google.com/group/cppba"
-~----------~----~----~----~------~----~------~--~---

Gabriel Viganotti | 2 May 2008 17:28
Picon

Re: Herencias en C++: 2/3

ah ta bien, en algun momento me imagine que era eso pero como despues decias en el texto que "Como se ve en este ultimo ejemplo, el polimorfismo esta dado en que, cualquier Comparador que se jacte de serlo, tiene que proveer un metodo comparar que reciba dos enteros, y devolver un bool." me entro la confusion.
gracias!

On Fri, May 2, 2008 at 1:21 PM, Daniel Gutson <danielgutson-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
Ya casi ni me acordaba de esto.
Devuelve int para ser generico, y retornar con la logica de strcmp  (-1, 0, +1)


On Fri, May 2, 2008 at 6:58 AM, Gabriel Viganotti <gabrielviganotti-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
Hola Dani,

muy lindo, me gusto. Solo para asegurarme que no me estoy perdiendo ningun detalle (o que no me estoy perdiendo :-) ), el metodo entonces devuelve bool y no int verdad?



On Mon, Apr 14, 2008 at 5:18 PM, Daniel Gutson <danielgutson-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
Sigo con
  3) usos + avanzados: template design pattern & mixins, private inheritance, curiously recursive template pattern
 
=================================================================
Ya hubo un adelanto de 'private inheritance' (ejemplos de Soledad, politicos corruptos y demas).
 
Sigo con tres usos un cacho mas complejos de herencia en C++: template design pattern & mixins, CRTP, y un caso practico de este ultimo: aspect oriented programming.
 
a) Template Design Pattern.
 
 Este pattern intenta resolver lo siguiente: cuando existen varios 'sabores' de un algoritmo, pero todos tienen en comun la misma secuencia de pasos. Lo que varia, es la implementacion de uno o mas de esos pasos.
Por ejemplo: odenar tanto de > como de <, el algoritmo no cambia, lo que cambia es la implementacion de la comparacion.
 
Voy a mostrar esto como se hace de las dos maneras: usando polimorfismo por inclusion, y polimorfismo parametrico, con mi sorting favorito (el selection).
 
El pseudocodigo como todo mundo conoce:
      for i = 1 .. n-1
        j = mejor_del_rango(i, n);
        if  (i != j)
           swap v[i], v[j]
 
y mejor_del_rango selecciona, de acuerdo a algun criterio el mejor o el mayor del rango pedido. Esto va a denotar el 'sabor'.
 
Entonces, la idea del Template Design Pattern, es ubicar los pasos a la clase base, y dejar que una derivada implemente el 'sabor'.
Ej:
    class SelectionSort
    {
         public: void sort(vector<int>& v);
    private:
         virtual int comparar(int x, int y) const = 0;
    };
 
   class MenorAMayor: public SelectionSort
   {
        private: virtual int comparar(int x, int y) const { return x < y; }
   };
 
Esto es: la clase base hace de master, y la derivada de slave. Osea, la base tiene la manijita, y le pregunta a la derivada "que onda x e y?".
Asi las cosas, un usuario instancia un MenorAMayor por ejemplo, e invoca el metodo publico de la clase base: sort.
 
 
Pasando a la version parametrica:
 
template <class Comparador>
class SelectionSort
{
    void sort(vector<int>& vec, Comparador& c)
    {
          .... c.comparar(vec[i], vec[j]);
    }
};
 
Como se ve en este ultimo ejemplo, el polimorfismo esta dado en que, cualquier Comparador que se jacte de serlo, tiene que proveer un metodo comparar que reciba dos enteros, y devolver un bool. La clase SelectionSort sigue teniendo la manijita, y usa al Comparador para preguntarle qué onda.
Esto ultimo tambien se conoce como 'policy class' o 'traits' (en este caso, la clase Comparador es la policy class, o politica de comparacion).
 
Es muy importante en esto tener en claro los roles: quien hace de master y quien de slave.
 
Como me quedó el mail muy largo, dejo los otros temas para un "Herencias en C++: 2.1/3".
 
Solo comparo brevemente las dos versiones: polimorfismo por inclusion o parametrico.
Ventajas de la version x inclusion:
   * ejecutable mas chico
   * mas legible
   * errores de compilacion mas claros.
   * codigo mas ordenado (no requiere inlines, por lo que todo puede estar organizado en .cpp y .h)
 
Ventajas de la version parametrica:
  * mas performante en general. Habilita inlining.
 
 
PERO OJO: lo importante es que NO se mezclen los tipos de polimorfismo. Regla general: si usas 'virtual' y 'template' en la misma clase, tiene Oracle (oloráculo).
 
  Daniel.





--
Gabriel Viganotti
Cel: +44 7795491396

"Monday's problems are the result of Friday's fatigue"







--
Gabriel Viganotti
Cel: +44 7795491396

"Monday's problems are the result of Friday's fatigue"
--~--~---------~--~----~------------~-------~--~----~
¿Eres miembro de "CyC++ Buenos Aires" verdad? Si no lo eres, has recibido este mesaje por error.
En caso de duda visita "http://groups.google.com/group/cppba"
-~----------~----~----~----~------~----~------~--~---

Soledad Alborno | 2 May 2008 17:46
Picon

creationPolicy


Hola, Estuve jugando un poco con lo de politicas, y quize hacer una 
politica que defina si una clase va a ser usada como singleton o no...
Pero no puedo hacer que compile por un tema de recursion de templates me 
parece, y hay un friend que no le gusta...
Quién se anima a hacer que compile ?
Saludos!
Sole

#include <iostream>

using namespace std;

template <class T>
class SingletonCreationPolicy{
public:
       static T & getInstance(){
           static T instance;
           return instance;
       }
};

template <class T>
class MultipleObjectCreationPolicy{
public:
       static  T & getInstance(){
           T object;
           return object;
       }
};
template <class CreationPolicy>
class MyFoolClass{
public:
       friend class CreationPolicy;
       static MyFoolClass & getInstance(){
                    MyFoolClass & instance = CreationPolicy::getInstance();
                    instance.count++;
                    return instance;
       }
       int getCount(){
           return count;
       }
private:
       MyFoolClass(){
                     count = 0;
       }

       int count;
};

typedef MyFoolClass<SingletonCreationPolicy<MyFoolClass> > SingletonClass;
typedef MyFoolClass<MultipleObjectCreationPolicy<MyFoolClass> > 
MultipleObjectsClass;

int main(int argc, char *argv[])
{

    SingletonClass sc = SingletonClass::getInstance();
    cout << "sc.count=" << sc.getCount() <<endl;
    SingletonClass sc2 = SingletonClass::getInstance();
    cout << "sc.count=" << sc.getCount()<< " sc2.count=" << 
sc2.getCount() <<endl;

    MultipleObjectsClass moc = MultipleObjectsClass::getInstance();
    cout << "moc.count=" << moc.getCount() <<endl;
    MultipleObjectsClass moc2 = MultipleObjectsClass::getInstance();
    cout << "moc.count=" << moc.getCount()<< " moc2.count=" << 
moc2.getCount() <<endl;

    int i;
    cin >> i;
}

Daniel Gutson | 2 May 2008 18:09
Picon

Re: Herencias en C++: 2/3

Lo tuyo no es confusion, es http://en.wikipedia.org/wiki/Confucious
 
  :D
 
pd: okokok, no me quieras echar del foro a mi tb.

 
On 5/2/08, Gabriel Viganotti <gabrielviganotti-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
ah ta bien, en algun momento me imagine que era eso pero como despues decias en el texto que "Como se ve en este ultimo ejemplo, el polimorfismo esta dado en que, cualquier Comparador que se jacte de serlo, tiene que proveer un metodo comparar que reciba dos enteros, y devolver un bool." me entro la confusion.
gracias!


On Fri, May 2, 2008 at 1:21 PM, Daniel Gutson <danielgutson-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
Ya casi ni me acordaba de esto.
Devuelve int para ser generico, y retornar con la logica de strcmp  (-1, 0, +1)


On Fri, May 2, 2008 at 6:58 AM, Gabriel Viganotti <gabrielviganotti-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
 
Hola Dani,

muy lindo, me gusto. Solo para asegurarme que no me estoy perdiendo ningun detalle (o que no me estoy perdiendo :-) ), el metodo entonces devuelve bool y no int verdad?



On Mon, Apr 14, 2008 at 5:18 PM, Daniel Gutson <danielgutson-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
Sigo con
  3) usos + avanzados: template design pattern & mixins, private inheritance, curiously recursive template pattern
 
=================================================================
Ya hubo un adelanto de 'private inheritance' (ejemplos de Soledad, politicos corruptos y demas).
 
Sigo con tres usos un cacho mas complejos de herencia en C++: template design pattern & mixins, CRTP, y un caso practico de este ultimo: aspect oriented programming.
 
a) Template Design Pattern.
 
 Este pattern intenta resolver lo siguiente: cuando existen varios 'sabores' de un algoritmo, pero todos tienen en comun la misma secuencia de pasos. Lo que varia, es la implementacion de uno o mas de esos pasos.
Por ejemplo: odenar tanto de > como de <, el algoritmo no cambia, lo que cambia es la implementacion de la comparacion.
 
Voy a mostrar esto como se hace de las dos maneras: usando polimorfismo por inclusion, y polimorfismo parametrico, con mi sorting favorito (el selection).
 
El pseudocodigo como todo mundo conoce:
      for i = 1 .. n-1
        j = mejor_del_rango(i, n);
        if  (i != j)
           swap v[i], v[j]
 
y mejor_del_rango selecciona, de acuerdo a algun criterio el mejor o el mayor del rango pedido. Esto va a denotar el 'sabor'.
 
Entonces, la idea del Template Design Pattern, es ubicar los pasos a la clase base, y dejar que una derivada implemente el 'sabor'.
Ej:
    class SelectionSort
    {
         public: void sort(vector<int>& v);
    private:
         virtual int comparar(int x, int y) const = 0;
    };
 
   class MenorAMayor: public SelectionSort
   {
        private: virtual int comparar(int x, int y) const { return x < y; }
   };
 
Esto es: la clase base hace de master, y la derivada de slave. Osea, la base tiene la manijita, y le pregunta a la derivada "que onda x e y?".
Asi las cosas, un usuario instancia un MenorAMayor por ejemplo, e invoca el metodo publico de la clase base: sort.
 
 
Pasando a la version parametrica:
 
template <class Comparador>
class SelectionSort
{
    void sort(vector<int>& vec, Comparador& c)
    {
          .... c.comparar(vec[i], vec[j]);
    }
};
 
Como se ve en este ultimo ejemplo, el polimorfismo esta dado en que, cualquier Comparador que se jacte de serlo, tiene que proveer un metodo comparar que reciba dos enteros, y devolver un bool. La clase SelectionSort sigue teniendo la manijita, y usa al Comparador para preguntarle qué onda.
Esto ultimo tambien se conoce como 'policy class' o 'traits' (en este caso, la clase Comparador es la policy class, o politica de comparacion).
 
Es muy importante en esto tener en claro los roles: quien hace de master y quien de slave.
 
Como me quedó el mail muy largo, dejo los otros temas para un "Herencias en C++: 2.1/3".
 
Solo comparo brevemente las dos versiones: polimorfismo por inclusion o parametrico.
Ventajas de la version x inclusion:
   * ejecutable mas chico
   * mas legible
   * errores de compilacion mas claros.
   * codigo mas ordenado (no requiere inlines, por lo que todo puede estar organizado en .cpp y .h)
 
Ventajas de la version parametrica:
  * mas performante en general. Habilita inlining.
 
 
PERO OJO: lo importante es que NO se mezclen los tipos de polimorfismo. Regla general: si usas 'virtual' y 'template' en la misma clase, tiene Oracle (oloráculo).
 
  Daniel.





 
--
 
Gabriel Viganotti
Cel: +44 7795491396

"Monday's problems are the result of Friday's fatigue"

 



 



--
Gabriel Viganotti
Cel: +44 7795491396

"Monday's problems are the result of Friday's fatigue"
--~--~---------~--~----~------------~-------~--~----~
¿Eres miembro de "CyC++ Buenos Aires" verdad? Si no lo eres, has recibido este mesaje por error.
En caso de duda visita "http://groups.google.com/group/cppba"
-~----------~----~----~----~------~----~------~--~---

Daniel Gutson | 2 May 2008 18:22
Picon

Re: creationPolicy

A mí ya me compila, pero te voy a ayudar a que te compile a vos.
 
1) Problema de recursion de templates: lo que esta mal aca, es que lo que recibis no es una clase, sino justamente, un TEMPLATE. Es decir, algo al que le puedas aplicar <>
 
2) Vos no queres que sea amigo de un template, sino de una instanciacion en particular. Friend templates no esta disponible en este C++.
 
  Daniel.

 
On 5/2/08, Soledad Alborno <soledad.alborno-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:

Hola, Estuve jugando un poco con lo de politicas, y quize hacer una
politica que defina si una clase va a ser usada como singleton o no...
Pero no puedo hacer que compile por un tema de recursion de templates me
parece, y hay un friend que no le gusta...
Quién se anima a hacer que compile ?
Saludos!
Sole

#include <iostream>

using namespace std;

template <class T>
class SingletonCreationPolicy{
public:
      static T & getInstance(){
          static T instance;
          return instance;
      }
};

template <class T>
class MultipleObjectCreationPolicy{
public:
      static  T & getInstance(){
          T object;
          return object;
      }
};
template <class CreationPolicy>
class MyFoolClass{
public:
      friend class CreationPolicy;
      static MyFoolClass & getInstance(){
                   MyFoolClass & instance = CreationPolicy::getInstance();
                   instance.count++;
                   return instance;
      }
      int getCount(){
          return count;
      }
private:
      MyFoolClass(){
                    count = 0;
      }

      int count;
};

typedef MyFoolClass<SingletonCreationPolicy<MyFoolClass> > SingletonClass;
typedef MyFoolClass<MultipleObjectCreationPolicy<MyFoolClass> >
MultipleObjectsClass;


int main(int argc, char *argv[])
{

   SingletonClass sc = SingletonClass::getInstance();
   cout << "sc.count=" << sc.getCount() <<endl;
   SingletonClass sc2 = SingletonClass::getInstance();
   cout << "sc.count=" << sc.getCount()<< " sc2.count=" <<
sc2.getCount() <<endl;

   MultipleObjectsClass moc = MultipleObjectsClass::getInstance();
   cout << "moc.count=" << moc.getCount() <<endl;
   MultipleObjectsClass moc2 = MultipleObjectsClass::getInstance();
   cout << "moc.count=" << moc.getCount()<< " moc2.count=" <<
moc2.getCount() <<endl;

   int i;
   cin >> i;
}


--~--~---------~--~----~------------~-------~--~----~
¿Eres miembro de "CyC++ Buenos Aires" verdad? Si no lo eres, has recibido este mesaje por error.
En caso de duda visita "http://groups.google.com/group/cppba"
-~----------~----~----~----~------~----~------~--~---

Soledad Alborno | 2 May 2008 18:52
Picon

Re: creationPolicy

De esta forma compila em comeau (con un warning imperdonable que ya modificaré).. tambien compila en Visual Studio
pero me parece que no compila en g++ puede ser?

saludotes
sole

#include <iostream>

using namespace std;

template <class T>
class SingletonCreationPolicy{
public:
       static T & getInstance(){
           static T instance;
           return instance;
       }
};

template <class T>
class MultipleObjectCreationPolicy{
public:
       static  T & getInstance(){
           T object;
           return object;
       }
};

template <template <class> class CreationPolicy >
class MyFoolClass{
public:
       friend class CreationPolicy<MyFoolClass>;
       static MyFoolClass & getInstance(){
                    MyFoolClass & instance = CreationPolicy<MyFoolClass>::getInstance();
                    instance.count++;
                    return instance;
       }
       int getCount(){
           return count;
       }
private:
       MyFoolClass(){
                     count = 0;
       }
      
       int count;
};

typedef MyFoolClass<SingletonCreationPolicy > SingletonClass;
typedef MyFoolClass<MultipleObjectCreationPolicy > MultipleObjectsClass;


int main(int argc, char *argv[])
{

    SingletonClass sc = SingletonClass::getInstance();
    cout << "sc.count=" << sc.getCount() <<endl;
    SingletonClass sc2 = SingletonClass::getInstance();
    cout << "sc.count=" << sc.getCount()<< " sc2.count=" << sc2.getCount() <<endl;
   
    MultipleObjectsClass moc = MultipleObjectsClass::getInstance();
    cout << "moc.count=" << moc.getCount() <<endl;
    MultipleObjectsClass moc2 = MultipleObjectsClass::getInstance();
    cout << "moc.count=" << moc.getCount()<< " moc2.count=" << moc2.getCount() <<endl;
   
    int i;
    cin >> i;
}



Daniel Gutson wrote:
A mí ya me compila, pero te voy a ayudar a que te compile a vos.
 
1) Problema de recursion de templates: lo que esta mal aca, es que lo que recibis no es una clase, sino justamente, un TEMPLATE. Es decir, algo al que le puedas aplicar <>
 
2) Vos no queres que sea amigo de un template, sino de una instanciacion en particular. Friend templates no esta disponible en este C++.
 
  Daniel.

 
On 5/2/08, Soledad Alborno <soledad.alborno-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:

Hola, Estuve jugando un poco con lo de politicas, y quize hacer una
politica que defina si una clase va a ser usada como singleton o no...
Pero no puedo hacer que compile por un tema de recursion de templates me
parece, y hay un friend que no le gusta...
Quién se anima a hacer que compile ?
Saludos!
Sole

#include <iostream>

using namespace std;

template <class T>
class SingletonCreationPolicy{
public:
      static T & getInstance(){
          static T instance;
          return instance;
      }
};

template <class T>
class MultipleObjectCreationPolicy{
public:
      static  T & getInstance(){
          T object;
          return object;
      }
};
template <class CreationPolicy>
class MyFoolClass{
public:
      friend class CreationPolicy;
      static MyFoolClass & getInstance(){
                   MyFoolClass & instance = CreationPolicy::getInstance();
                   instance.count++;
                   return instance;
      }
      int getCount(){
          return count;
      }
private:
      MyFoolClass(){
                    count = 0;
      }

      int count;
};

typedef MyFoolClass<SingletonCreationPolicy<MyFoolClass> > SingletonClass;
typedef MyFoolClass<MultipleObjectCreationPolicy<MyFoolClass> >
MultipleObjectsClass;


int main(int argc, char *argv[])
{

   SingletonClass sc = SingletonClass::getInstance();
   cout << "sc.count=" << sc.getCount() <<endl;
   SingletonClass sc2 = SingletonClass::getInstance();
   cout << "sc.count=" << sc.getCount()<< " sc2.count=" <<
sc2.getCount() <<endl;

   MultipleObjectsClass moc = MultipleObjectsClass::getInstance();
   cout << "moc.count=" << moc.getCount() <<endl;
   MultipleObjectsClass moc2 = MultipleObjectsClass::getInstance();
   cout << "moc.count=" << moc.getCount()<< " moc2.count=" <<
moc2.getCount() <<endl;

   int i;
   cin >> i;
}






--~--~---------~--~----~------------~-------~--~----~
¿Eres miembro de "CyC++ Buenos Aires" verdad? Si no lo eres, has recibido este mesaje por error.
En caso de duda visita "http://groups.google.com/group/cppba"
-~----------~----~----~----~------~----~------~--~---

Soledad Alborno | 2 May 2008 18:55
Picon

[Fwd: Re: [cppba] Re: creationPolicy]

No compila con mingw... :)
besos
sole

-------- Original Message -------- Subject: Date: From: To: References:
Re: [cppba] Re: creationPolicy
Fri, 02 May 2008 13:52:56 -0300
Soledad Alborno <soledad.alborno-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
cppba-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
<481B3752.6020809-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> <23ab4d1c0805020922m70bf8dfw80388ccfe4e5d3e3-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>


De esta forma compila em comeau (con un warning imperdonable que ya modificaré).. tambien compila en Visual Studio
pero me parece que no compila en g++ puede ser?

saludotes
sole

#include <iostream>

using namespace std;

template <class T>
class SingletonCreationPolicy{
public:
       static T & getInstance(){
           static T instance;
           return instance;
       }
};

template <class T>
class MultipleObjectCreationPolicy{
public:
       static  T & getInstance(){
           T object;
           return object;
       }
};

template <template <class> class CreationPolicy >
class MyFoolClass{
public:
       friend class CreationPolicy<MyFoolClass>;
       static MyFoolClass & getInstance(){
                    MyFoolClass & instance = CreationPolicy<MyFoolClass>::getInstance();
                    instance.count++;
                    return instance;
       }
       int getCount(){
           return count;
       }
private:
       MyFoolClass(){
                     count = 0;
       }
      
       int count;
};

typedef MyFoolClass<SingletonCreationPolicy > SingletonClass;
typedef MyFoolClass<MultipleObjectCreationPolicy > MultipleObjectsClass;


int main(int argc, char *argv[])
{

    SingletonClass sc = SingletonClass::getInstance();
    cout << "sc.count=" << sc.getCount() <<endl;
    SingletonClass sc2 = SingletonClass::getInstance();
    cout << "sc.count=" << sc.getCount()<< " sc2.count=" << sc2.getCount() <<endl;
   
    MultipleObjectsClass moc = MultipleObjectsClass::getInstance();
    cout << "moc.count=" << moc.getCount() <<endl;
    MultipleObjectsClass moc2 = MultipleObjectsClass::getInstance();
    cout << "moc.count=" << moc.getCount()<< " moc2.count=" << moc2.getCount() <<endl;
   
    int i;
    cin >> i;
}



Daniel Gutson wrote:
A mí ya me compila, pero te voy a ayudar a que te compile a vos.
 
1) Problema de recursion de templates: lo que esta mal aca, es que lo que recibis no es una clase, sino justamente, un TEMPLATE. Es decir, algo al que le puedas aplicar <>
 
2) Vos no queres que sea amigo de un template, sino de una instanciacion en particular. Friend templates no esta disponible en este C++.
 
  Daniel.

 
On 5/2/08, Soledad Alborno <soledad.alborno-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:

Hola, Estuve jugando un poco con lo de politicas, y quize hacer una
politica que defina si una clase va a ser usada como singleton o no...
Pero no puedo hacer que compile por un tema de recursion de templates me
parece, y hay un friend que no le gusta...
Quién se anima a hacer que compile ?
Saludos!
Sole

#include <iostream>

using namespace std;

template <class T>
class SingletonCreationPolicy{
public:
      static T & getInstance(){
          static T instance;
          return instance;
      }
};

template <class T>
class MultipleObjectCreationPolicy{
public:
      static  T & getInstance(){
          T object;
          return object;
      }
};
template <class CreationPolicy>
class MyFoolClass{
public:
      friend class CreationPolicy;
      static MyFoolClass & getInstance(){
                   MyFoolClass & instance = CreationPolicy::getInstance();
                   instance.count++;
                   return instance;
      }
      int getCount(){
          return count;
      }
private:
      MyFoolClass(){
                    count = 0;
      }

      int count;
};

typedef MyFoolClass<SingletonCreationPolicy<MyFoolClass> > SingletonClass;
typedef MyFoolClass<MultipleObjectCreationPolicy<MyFoolClass> >
MultipleObjectsClass;


int main(int argc, char *argv[])
{

   SingletonClass sc = SingletonClass::getInstance();
   cout << "sc.count=" << sc.getCount() <<endl;
   SingletonClass sc2 = SingletonClass::getInstance();
   cout << "sc.count=" << sc.getCount()<< " sc2.count=" <<
sc2.getCount() <<endl;

   MultipleObjectsClass moc = MultipleObjectsClass::getInstance();
   cout << "moc.count=" << moc.getCount() <<endl;
   MultipleObjectsClass moc2 = MultipleObjectsClass::getInstance();
   cout << "moc.count=" << moc.getCount()<< " moc2.count=" <<
moc2.getCount() <<endl;

   int i;
   cin >> i;
}







--~--~---------~--~----~------------~-------~--~----~
¿Eres miembro de "CyC++ Buenos Aires" verdad? Si no lo eres, has recibido este mesaje por error.
En caso de duda visita "http://groups.google.com/group/cppba"
-~----------~----~----~----~------~----~------~--~---


Gmane