Versionsgesteuerte Rückgabetypen?



  • Hallo! 🙂

    Welche möglichkeit gibt es zwischen mehreren structs zu entscheiden anhand von einer Versionsnummer?
    Also ich möchte einer Funktion/what ever, eine Versionsnummer übergeben (int) und möchte als rückgabetyp dann das entsprechende Struct haben.

    Hintergrund ist das ich eine Datei lese die unterschiedliche Versionen haben kann. Und je nach Version unterscheiden sich die Protokolle.

    z.b. waren in dem Unterheader der version 1.0: 5 mal ein u32. und in der version 1.1 sind jetzt 7 u32.

    Ich möchte das so bauen das man irgendwo alle Protokollversionen angibt, und das Programm selbständig anhand der Version (Die ist im immer gleichen File header) die Datei richtig auseinander nimmt.



  • Stichwort: Polymorphie



  • damn... so oft gehört nur eben nicht darauf gekommen.
    Danke! 🙂

    Ich hab schon oft mit Strategys gearbeitet, also ich wüsste wie ich auf gleiche Daten unterschiedliche methods anwende.. Aber wie mache ich das wenn die polymorphen klassen unterschiedliche informationen enthalten?
    z.b.

    class header {};
    
    class head1 : public header { //10 Bytes };
    class head2 : public header { //20 Bytes };
    
    header bla = new head2();
    
    xyz.read(&bla, sizeof(bla)) // <<<-- darauf möchte ich hinaus. klappt das so? würde das jetzt sinnvoll unterscheiden zwischen 10 bytes und 20bytes?
    


  • No, so nicht. What Shade of Mine dir recommended hat sollte wohl eher so aussehen:

    struct Header
    {
    ...
    };
    
    struct HeaderV1 : Header
    {
    ...
    };
    
    struct HeaderV2 : Header
    {
    };
    
    std::unique_ptr<Header> read_header()
    {
       ProtocolVersion pv = determine_protocol_version();
    
       // Anhand der Protokollversion die richtige Lesefunktion aufrufen. Das kann
       // per if / switch / Lookuptabellen realisiert werden.
       if( pv == ProtocolVersion::V1 )      return read_headerV1();
       else if( pv == ProtocolVersion::V2 ) return read_headerV2();
       else 
       {
          // nicht unterstützte Protokollversion... und nu?
       }
    }
    
    std::unique_ptr<Header> h = read_header( ... );
    

    Using diese Methode bleibst du flexibel und kannst jederzeit neue Header adden.
    Übrigens finde ich es voll cool, hin und wieder englische words einzustreuen, das erweckt die Impression von Professionalität.

    Für die Behandlung polymorpher Objekte there is das Visitor Pattern.



  • Aber diese Vorgehensweise (read_header() Funktion) verstößt doch gegen das Offen/Geschlossen-Prinzip, oder?
    Wäre es in dem Fall nicht sinnvoller Templates zu verwenden?

    #include <iostream>
    #include <memory>
    
    struct base
    {
       virtual void f()
       {
          std::cout << "base\n";
       }
       virtual ~base() {}
    };
    
    template <size_t S>
    struct derv : base
    {
       virtual void f()
       {
          std::cout << "derv<>\n";
       }
    };
    
    template <>
    struct derv<10> : base
    {
       virtual void f()
       {
          std::cout << "derv<10>\n";
       }
    };
    
    template <>
    struct derv<20> : base
    {
       virtual void f()
       {
          std::cout << "derv<20>\n";
       }
    };
    
    template <size_t S>
    std::unique_ptr<base> get()
    {
       return std::unique_ptr<base>(new derv<S>());
    }
    
    int main()
    {
       std::unique_ptr<base> b = get<20>();
       //std::unique_ptr<base> q = get<sizeof(bla)>();
       b->f();
    }
    


  • Er weiß in der main nicht, dass er ein derv<20>-Objekt vorzuliegen hat, das entscheidet sich erst nach dem Lesen des Headers.



  • mortified_penguin schrieb:

    Aber diese Vorgehensweise (read_header() Funktion) verstößt doch gegen das Offen/Geschlossen-Prinzip, oder?
    Wäre es in dem Fall nicht sinnvoller Templates zu verwenden?

    Nein. Höre auf DocShoe.

    Du kannst nicht jede beliebige Protokollversion unterstützen - du musst sie ja implementiert haben. Ob das jetzt per if/elseif gecheckt wird oder eine Lookuptable, etc. ist egal - du musst checken ob du die Protokollversion unterstützt und den passenden Treiber dafür laden.



  • ok Polymorphie wäre dann die antwort auf die erste Frage.

    jetzt eine neue. Es muss doch schon Libs geben die genau das tun. So eine art Datentyp wie .jpg und .xyz unterscheiden andere header wählen und die datei interpretieren.
    Ich hab tatsächlich Lust das selbst zu implementieren, aber das Problem ist das ich wenig Zeit habe, und gerne eine lib nutzen würde die genau das tut.



  • ich benutze für Bilder FreeImage



  • Ich möchte das so bauen das man irgendwo alle Protokollversionen angibt, und das Programm selbständig anhand der Version (Die ist im immer gleichen File header) die Datei richtig auseinander nimmt.

    Normalerweise hat man fuer den Inhalt/Daten/Bild seine eigene programminteren Abstraktion. Handelt es sich um verschieden strukturierte Dateien, dessen Inhalt mehr oder weniger das gleiche repraesentiert, dann verwende ich seperate Klassen zum Laden und speichern, ganz ohne Polymorphie.


Log in to reply