Framework-Design / Virtuelle Klassen



  • Folgende Aufgabenstellung: Es soll ein kleiners Datenbank-Framework mit Hilfe von abstrakten (also virtuellen) Klassen erstellt werden. Die virtuellen Klassen dürfen keinerlei Variablen beinhalten. Die abgeleiteten Klassen sollen eine unbekannte Anzahl Werte unterstützen.

    Also in etwa so:

    class Value
    {
    //Keine Variablen
    public:
    virtual (irgendein Typ) getValue(int ValueType);
    virtual void setValue( int ValueType, (irgendeinTyp) Value);
    };
    
    class MyValue: public Value
    {
    //Irgendwelche Variablen
    bool Boolean1;
    bool Boolean2;
    
    virtual (irgendein Typ) getValue(int ValueType);
    virtual void setValue( int ValueType, (irgendeinTyp) Value);
    };
    
    //Bspw:
    bool MyValue::getValue(int ValueType)
    {
    
    if(ValueType == 1)
    {
    return Boolean2;
    }
    
    return Boolean1;
    }
    
    class Database
    {
    ...
    std::vector<boost::shared_ptr<Value*> > WerteListe;
    
    ...
    };
    

    PS: MyValue ist kein Teil des Frameworks sondern soll nur zeigen wie man dann die abstrakte Klasse Value nutzen könnte.

    Frage:
    Geht das nicht einfacher bzw. schöner? 😕
    So muss für jede Art einer Variable (bool, int, long usw.) eine eigene get/set-Methode erstellt werden. Ausserdem finde ich die Kombination von Vector und abgeleiteten Klassen ultra-hässlich! (Ohne shared_pointer ist es fast unmöglich an Memory Leaks vorbei zu kommen!).

    Eine Möglichkeit wäre noch die Get-/Set-Methoden normal zu definieren (ohne virtual) so müsste man die Funktion überladen, solange sie nicht überladen ist geben sie einfach NULL bzw. false zurück. Ist aber auch nicht wirklich schön.



  • Wie wäre es mit einem template?

    template<class T, class U>
    class MyValue: public Value
    {
    //Irgendwelche Variablen
    bool Boolean1;
    bool Boolean2;
    
    virtual U getValue(T ValueType);
    virtual void setValue( T ValueType, U Value);
    };
    

    EDIT:
    Respektive müsstest du bei der Basisklasse dann die beiden Funktionen auch noch template Funktionen draus machen, wo du dann jeweils den gewünschten Typen angeben kannst.


  • Mod

    drakon schrieb:

    Respektive müsstest du bei der Basisklasse dann die beiden Funktionen auch noch template Funktionen draus machen, wo du dann jeweils den gewünschten Typen angeben kannst.

    Allerdings sind Templatememberfunktionen aus gutem Grund niemals virtuell.

    Mir scheint das kein geeigneter Fall für Vererbung zu sein, weil die Menge zulässiger Argumente von der Implementation der abgeleiteten Klassen abhängen würde.

    Spontan fällt mir so etwas ein:

    template <typename T>
    class TValue
    {
        virtual T getValue(int ValueType) const = 0;
        virtual void setValue(int ValueType, const T& Value) = 0;
        virtual ~TValue() {}
    };
    
    class Value
    {
    //Keine Variablen
    public:
        template <typename T>
        T getValue(int ValueType) const
        {
            if ( const TValue<T>* p = dynamic_cast<const TValue<T>*>( this ) )
                return p->getValue( ValueType );
            throw /*up*/...;
        }
        template <typename T>
        void setValue(int ValueType, const T& Value)
        {
            if ( TValue<T>* p = dynamic_cast<TValue<T>*>( this ) )
                return p->setValue( ValueType, Value );
            throw /*up*/...;
        }
        virtual ~Value() {}
    };
    
    class Irgendwas_mit_int_oder_double : public Value, public TValue<int>, public TValue<double>
    {
    ...
    


  • camper schrieb:

    drakon schrieb:

    Respektive müsstest du bei der Basisklasse dann die beiden Funktionen auch noch template Funktionen draus machen, wo du dann jeweils den gewünschten Typen angeben kannst.

    Allerdings sind Templatememberfunktionen aus gutem Grund niemals virtuell.

    Hm. Ja. Ich dachte ich habe mal was ähnliches gemacht, dort hatte ich aber keine Polymorphie..



  • Du koenntest auch die verschiedenen Typen wie double, char*, ... mittels union wrappen und ein Flag setzen. Ueber Methoden a la isDouble kannst du den tatsaechlichen Typ zur Laufzeit identifizieren.



  • Rookie86 schrieb:

    Folgende Aufgabenstellung: Es soll ein kleiners Datenbank-Framework mit Hilfe von abstrakten (also virtuellen) Klassen erstellt werden. Die virtuellen Klassen dürfen keinerlei Variablen beinhalten.

    Gewöhn dir gleich mal ab selbst erfundene Begriffe wie "virtuelle Klassen" zu verwenden. Den gibt's nicht, und er macht keinen Sinn.

    Was es noch gibt ist der Begriff Interface oder Interface-Klasse - der oft für Klassen verwendet wird die ausschliesslich (oder fast ausschliesslich) aus "pure virtual" Funktionen bestehen.



  • Du koenntest auch die verschiedenen Typen wie double, char*, ... mittels union wrappen und ein Flag setzen. Ueber Methoden a la isDouble kannst du den tatsaechlichen Typ zur Laufzeit identifizieren.

    Genau so etwas habe ich gesucht! 😃


Anmelden zum Antworten