Ver Mensaje Individual
  #6 (permalink)  
Antiguo 15/09/2010, 05:06
Avatar de r0d
r0d
 
Fecha de Ingreso: noviembre-2007
Mensajes: 86
Antigüedad: 16 años, 5 meses
Puntos: 3
Respuesta: Duda sobre plantillas

Se puede hacer algo parecido al java: hacer una clase madre para todos tus tipos General. Es lo que hace java con su super_object (Object).

Por ejemplo:
Código:
#include <iostream>
#include <vector>
#include <string>
#include <sstream>

using namespace std;

struct ValueType
{
    virtual ~ValueType() {} // el destructor siempre virtual si la clase tiene que ser heredada
    virtual const int ToInt() const = 0;
    virtual const string ToStr() const = 0;
};

struct ValueType0 : public ValueType
{
    explicit ValueType0( int val = 0 ) : int_value( val ) {}

    const int ToInt() const { return int_value; 
    }

    const string ToStr() const {
        ostringstream oss;
        oss << int_value;
        return oss.str();
    }

protected:
    int int_value;
};

struct ValueType1 : public ValueType
{
    explicit ValueType1( const string & str = "n/a" ) : str_value ( str ) {}

    const int ToInt() const {
        istringstream iss( str_value );
        int ret_val;
        iss >> ret_val;
        return ret_val;
    }
    
    const string ToStr() const {
        return str_value;
    }

protected:
    string str_value;
};

//------------


struct Genoma
{
    ~Genoma() {
        for ( vector<ValueType*>::iterator it = values.begin(); it != values.end(); ++it )
            delete *it;
    }

    void PushValue( ValueType * value ) {
        values.push_back( value );
    }

    void PrintValue( size_t index ) {
        if ( index >= values.size() )
            cout << "index: " << index << " out of range" << endl;
        else
            cout << values[index]->ToStr() << endl;
    }

private:
    vector<ValueType*> values;
};

int main()
{    
    Genoma genoma;
    genoma.PushValue( new ValueType0( 109 ) );
    genoma.PushValue( new ValueType1( "test" ) );
    genoma.PrintValue(0);
    genoma.PrintValue(1);
    genoma.PrintValue(2);

    cout << endl << "end" << endl;
    cin.get();
    return 0;
}

Esta solución es tipicamente un enfoque "contrato". Es decir que todos los tipos que van a estar utilizados en la clase Genoma tienen que implementar la interfaz virtual del tipo mas alto (ValueType en mi ejemplo).

Existen otras soluciones, pero depiende lo que quieres hacer exactamente con estes values.

java permite esto, pero tiene un coste: cada objeto hereda del super_object (Object), y asi todos los objetos tienen una tabla virtual (en C++ solo los objetos que tienen funciones virtuales tienen una), y esta tabla virtual ya esta bien llena en java. Y esto implica perdidas en termino de rapidez de ejecución.

El c++ no tiene esta politica con los tipos, y para algunas cosas, hay que encontrar soluciones adaptadas. Por ejemplo, el problema de la reflexividad es complicado en C++, aunque en otros langajes (java o C# por ejemplo), no es un problema porque los tipos tienen datos en el runtime.
__________________
Alicia: Sólo quiero saber que camino debo tomar.
Gato risón: Pues... depende mucho de donde quieras ir.

Mi página web