[Designproblem] Nachfahren und Operatoren der Vorfahren



  • Speed schrieb:

    Tachyon schrieb:

    Führt B (und alle Nachfahren) denn auch neue Daten ein?

    Nein. Alle Klassen sind PODs die keine weiteren Daten einführen( damit sie ua in unions anderer klassen verwendet werden können)

    Dann würde ich das nicht mit Vererbung lösen. Auch der Ansatz, dass erbende Klassen andere Regeln für Multiplikation haben sollen, ist meiner Meinung nach ein Designfehler.
    Wenn B von A erbt, dann sollte sich B genauso verhalten wie A. Dem ist aber nicht mehr so, wenn B * B was anderes ergibt als A * A.



  • A operator*( A const& lhs , int const& rhs );
    A operator*(int const& rhs ,  A const& lhs );
    
    c1 = c1 * ~c2; // geht nicht da ~c2 ein objekt von Klasse B zurückgibt...
    

    Was sagt denn der Compiler? Welche Fehlermeldung? Nach der besagten Operation erhaelt man ein Object vom Typ A. Beruecksichtigt man noch die anderen Regeln, so verwundert es mich, dass der Kompiler nicht total verwirrt ist.



  • Speed schrieb:

    hmm ja stimmt, das wäre eine Lösung. Aber dann müsste ich Alle Operatoren(und Funktionen) von A in B neu implementieren und diese wiederum in C und allen nachfahren auf gleiche weise reimplementieren. Als Tippfauler Programmierer gefällt mir das nicht...

    Schau dir evtl. mal boost::operators an. Ich hab da hier im Magazin auch zwei Artikel drüber geschrieben:
    Einführung in boost::operators
    boost::operators für Fortgeschrittene
    Damit könntest du dir evtl. eine ganze Menge Arbeit sparen.



  • Tachyon schrieb:

    Wenn B von A erbt, dann sollte sich B genauso verhalten wie A. Dem ist aber nicht mehr so, wenn B * B was anderes ergibt als A * A.

    A * A gibt es nicht ...

    Die Klassen redefinieren die Operatoren nicht , jede Vererbung führt weitere ein...

    Konkrete Beispiele für die dritte vererbungsebene wären

    - Quaternionen mit reinem komplexen inhalt
    - Quaternionen mit dualen oder Double-zahlen
    - duale Vektoren , komplexe Vektoren

    alle haben einige gemeinsamkeiten zb die Komplementierung die in 'B' eingeführt wird; Multiplikation wird erst in der dritten ebene eingefürt( da sie sich überall unterscheidet).



  • Also werden (anscheinend in der dritten Ebene) doch Attribute hinzugefügt. Wie soll denn z.B. das Komplement (welches ja auf der Ebene B arbeitet) für komplexe Vektoren aussehen? An der Stelle, an welcher der Komplement-Operator definiert wird, gibt es ja noch gar keine komplexen Vektoren.



  • Die einzigen attribute die eingeführt werden sind in A nämlich ein array das verwaltet wird...
    Für A gibt es kein Komplement...
    B ist eine Spezialisation von A(also auch ein A).Esn fasst alle gemeinsamen funktionen von C&co zusammen ...

    C&Co (vorhin genannte beispiele) besitzen gemeinsamkeiten die in B definiert sind und leiten weitere , für die klasse typische verhaltensweisen ein...

    so stellt B einen Vector da der nicht im gewohnten zahlenbereich liegt...

    Komplexe und duale(und andere "derivate") haben diese gemeinsamkeit; die multiplikationsregel untgerscheiden sich allerdings..(so ist bekannt, dass i*i ) -1 und d * d = 0 ist)

    theoretisch könnte ich B auflösen und in C&Co den Code direkt übernehmen..würde mein Problem lösen; ist aber unschön da das überall der gleiche code ist...

    @pumukl : schau ich mir an ..sieht auf den ersten Blick vielversprechend aus; (ist aber meine Klasse immer noch ein POD ?)

    EDIT : @Tachyon : das komplement wird erreicht, wenn man lediglich den NICHT-REELLEN teil Komplementiert -> also ein Minus davor stehlt...
    Sei float V[4] ein "nicht-reeller" vector so hat er ein reellen anteil und einen nicht reelle anteil( was bei mir die letzten drei Elemente sind)

    also sähe das komplement folgender massen aus :
    Komplement[0] =V[0]
    Komplement[1] = -V[1]
    Komplement[2] = -V[2]
    Komplement[3] = -V[3]


  • Mod

    Operatorüberladung und Vererbung passen regelmäßig nicht gut zusammen. Möglich wäre, implizite Konvertierungen von B nach C,D,E zu ermöglichen - dass das keine gute Idee ist, muss sicher nicht erläutert werden.
    Ansonsten ist eine eigenständige Funktion für jede Ableitung von B erforderlich. Die Struktur dieser Funktion hängt allerdings nicht von der konkreten Ableitung ab, somit bietet sich ein Funktionstemplate an.

    template <typename T>
    typename enable_if<is_convertible<T&,B&>,T>::type operator~(T rhs)
    {
        B& b = rhs;
        b = ~b;
        return rhs;
    }
    

    Speed schrieb:

    Tachyon schrieb:

    Führt B (und alle Nachfahren) denn auch neue Daten ein?

    Nein. Alle Klassen sind PODs die keine weiteren Daten einführen( damit sie ua in unions anderer klassen verwendet werden können)

    Ein POD enthält niemals Basisklassen, und eine Verwendung in unions ist erst recht ausgeschlossen.



  • camper schrieb:

    Operatorüberladung und Vererbung passen regelmäßig nicht gut zusammen. Möglich wäre, implizite Konvertierungen von B nach C,D,E zu ermöglichen - dass das keine gute Idee ist, muss sicher nicht erläutert werden.
    Ansonsten ist eine eigenständige Funktion für jede Ableitung von B erforderlich. Die Struktur dieser Funktion hängt allerdings nicht von der konkreten Ableitung ab, somit bietet sich ein Funktionstemplate an.

    template <typename T>
    typename enable_if<is_convertible<T&,B&>,T>::type operator~(T rhs)
    {
        B& b = rhs;
        b = ~b;
        return rhs;
    }
    

    Sieht aus als ob das währe was ich suche...
    Habe ein konstrukt wie dieses noch nie gesehn ; werde mich mal schlau machen wie das genau funktioniert.

    enable_if scheit nur T zu returnen wenn T in B konventierbar ist - würde zugern wissen wie das genau funktioniert.



  • Speed schrieb:

    enable_if scheit nur T zu returnen wenn T in B konventierbar ist - würde zugern wissen wie das genau funktioniert.

    google: "boost enable_if" sollte dir alles liefern was du brauchst 🙂



  • Speed schrieb:

    Mir fallen spontan 3 "schein" Lösungen ein.

    Templates sind mir da direkt eingefallen.
    Weiterhin geht das glaub ich sehr in die Richtung "policy-based design".

    Meiner Meinung nach brauchst du dafür nicht zwingend boost::enable_if. Müßte alles mit normalen "Hausmitteln" sofort gehen.

    Falls du noch nie mit Templates gearbeitet hast, solltest du dich da mal dringend reinarbeiten. Denn das springt einem doch förmlich ins Auge 😃



  • Vielen Dank
    ein "enable_if" marke eigenbau 😃 hat mein Problem gelöst...
    Templates waren mir zwar bekannt ( werden massenweise in meinem Projekt verwendet ), allerdings habe ich niemals "typenames" auserhalb der "template-definition" gesehn..

    Closed


Anmelden zum Antworten