Methoden mit bool-Parametern und "Lesbarkeit" im Kontext



  • Sobald man eine 2. Klasse an Flags einführt, die zB das Backbuffering oder das Thread-Verhalten betrifft, macht dieser Ansatz *bumm*.

    er ist halt nicht erweiterbar und im prinzip geht es dabei nur um die ersparung von schreibarbeit. Das ganze wird dann durch etwaige Syntaxprobleme, man denke nur mal daran dass Fenster oft nur Zeiger sind, erschwert.

    Es klappt zwar und erspart ne Menge schreibarbeit - aber im endeffekt verwirrt es den Leser:

    void show() {
      if(*this & Modal) {
      } else if(*this & Fullscreen) {
      }
    }
    

    und bedeutet ein enormes Problem bezüglich zukünftiger Erweiterungen:

    window.Mode = Fullscreen;
    window.Buffering = DoubleBuffering;
    

    das ganze mit der "eleganten Syntax":

    window = Fullscreen; //aja - das verwirrt garantiert nicht
    window = DoubleBuffering; //syntaktisch möglich - aber wen verwirrt das nicht?
    

    weiters dann das checken:

    if(win->Mode & Fullscreen)
    if(win->Buffering & DoubleBuffering)
    

    mit der "eleganten Syntax"

    if(*win & Fullscreen)
    if(*win & BackBuffering)
    

    Das Argument mit

    win->Windows::Flags & Modal
    

    ist etwas fragwürdig. Erstmal der Name "flags" ist furchtbar - aber ok.

    Wenn ich nun so dumm bin und die Flags von Windows und Dialog so trenne - dann habe ich das selbe Problem mit der "eleganten Syntax". Wenn Modal ein Flag von Dialog ist und Fullscreen einer von Dialog, dann ist sowas schon ziemlich dirty zu implementieren:

    win = Model | Fullscreen;
    

    natürlich möglich - aber dann wird die implementierung langsam häßlich.

    Man muss hier natürlich zwischen enum und einem Klassen Ansatz trennen - worum es hier geht ist, dass diese Vererbung gefährlich sein kann.

    Dieser Beitrag ist übrigens an die Leser dieses Threads gerichtet - damit sie hier nicht auf dumme Ideen kommen.



  • Shade Of Mine schrieb:

    Es klappt zwar und erspart ne Menge schreibarbeit - aber im endeffekt verwirrt es den Leser:

    void show() {
      if(*this & Modal) {
      } else if(*this & Fullscreen) {
      }
    }
    

    Das geht so natürlich nicht und das wirkt sich auch direkt auf die weiteren Folgerungen aus. Du musst den Datentyp angeben, da Du mit Klassen arbeitest und nicht mit Enums. Auch this wird ohne Klasse schwierig 😉

    void MyClass::show() {
      if(*this & DialogFlags::Modal) {
      } else if(*this & WindowFlags::Fullscreen) {
      }
    }
    

    Shade Of Mine schrieb:

    und bedeutet ein enormes Problem bezüglich zukünftiger Erweiterungen:
    das ganze mit der "eleganten Syntax":

    window = Fullscreen; //aja - das verwirrt garantiert nicht
    window = DoubleBuffering; //syntaktisch möglich - aber wen verwirrt das nicht?
    
    window = WindowFlags::Fullscreen;     // Flag setzen
    window = WindowMode::DoubleBuffering; // Mode setzen
    

    Shade Of Mine schrieb:

    mit der "eleganten Syntax"

    if(*win & Fullscreen)
    if(*win & BackBuffering)
    

    Der Punkt geht natürlich an Dich.

    Ich arbeite meist mit Referenzen, da brauche ich den * nicht.
    Für mich ist wichtig, dass die Alltagsfragen gut geklärt sind und *win spielt bei meinen Klassen kaum eine Rolle.

    Shade Of Mine schrieb:

    Wenn ich nun so dumm bin und die Flags von Windows und Dialog so trenne - dann habe ich das selbe Problem mit der "eleganten Syntax". Wenn Modal ein Flag von Dialog ist und Fullscreen einer von Dialog, dann ist sowas schon ziemlich dirty zu implementieren:

    win = Model | Fullscreen;
    

    natürlich möglich - aber dann wird die implementierung langsam häßlich.

    Sorry, das ist nicht möglich, da operator | ( WindowFlags &, DialogFlags & ) nicht definiert ist.

    Shade Of Mine schrieb:

    Dieser Beitrag ist übrigens an die Leser dieses Threads gerichtet - damit sie hier nicht auf dumme Ideen kommen.

    Auch für Dich gilt, dass persönliche Ablehnung vollkommen in Ordnung ist. Die Idee für dumm zu erklären, geht mir aber ein Schritt zuweit - zumal Du sie offensichtlich noch nicht ganz verstanden hattest.
    Die Idee ist eine Möglichkeit selbst wenn sie im Alltag nicht gefällt, ist das noch kein Grund, dass sie 'dumm' wäre.



  • Xin schrieb:

    Shade Of Mine schrieb:

    Wenn ich nun so dumm bin und die Flags von Windows und Dialog so trenne - dann habe ich das selbe Problem mit der "eleganten Syntax". Wenn Modal ein Flag von Dialog ist und Fullscreen einer von Dialog, dann ist sowas schon ziemlich dirty zu implementieren:

    win = Model | Fullscreen;
    

    natürlich möglich - aber dann wird die implementierung langsam häßlich.

    Sorry, das ist nicht möglich, da operator | ( WindowFlags &, DialogFlags & ) nicht definiert ist.

    Und genau das sind die Punkte die einen Anwender verwirren.

    Wenn ich

    win = Fullscreen;
    win = Modal;
    

    machen kann - dann muss ich plötzlich höllisch aufpassen was was ist. ich könnte immer:

    win |= Fullscreen;
    win |= Modal;
    

    machen - sieht komisch aus, geht aber.

    Das Problem dass dann an der Lesbarkeit auftritt ist aber -> man trennt die beiden Flags nicht also will ich eigentlich:

    win = Fullscreen | Modal;
    

    machen.

    Wenn man diese Trennung - die ja vorhanden ist - einfach nicht versteckt sondern öffentlich macht:

    win.Mode |= Fullscreen;
    win.DialogMode |= Modal;
    

    erkennt man wenigstens warum man da nicht Fullscreen | Modal machen kann. Wobei ich diese Trennung generell fragwürdig finde.

    Es verwirrt den Anwender, weil es sich unnatürlich verhält. Und unnatürliches verhalten ist wo immer es geht zu vermeiden.

    Aber auch dieser Beitrag geht nicht an Xin, sondern an etwaige leser.



  • window = WindowFlags::Fullscreen;     // Flag setzen 
    window = WindowMode::DoubleBuffering; // Mode setzen
    

    Ich finde die Syntax ziemlich elegant.

    if(*win & Fullscreen)
    if(*win & BackBuffering)
    

    Dies ist nich so verwirrend. Normal muss man ja auch machen:

    if ( win->flags & BackBuffering ) // ...
    

    Also ich finde die Syntax ziemlich elegant und auch nicht verwirrend. Es ist nur ungewoehnlich. Probleme bei der Klassenhierarchie sehe ich nicht so. Da alles nur statisch ablaeuft gibts auch keine Nachteile.

    Allerdings mal eine Frage, ist sowas moeglich:

    class MeineFlags { }
    
    class MeineErweitertenFlags : MeineFlags { }
    
    class Window : public MeineFlags, MeineErweitertenFlags {}
    

    Also kann ich MeineFlags erweitern, indem ich davon ableite? Muesste eigentlich gehen?

    if ( window & MeineFlags::foo ) { }
    else if if ( window & MeineErweitertenFlags::foo ) { }
    


  • win = Fullscreen | Modal;
    

    Sowas waere echt cool, wenns denn moeglich waere...

    Btw, endlich mal eine sinnvolle Verwendung von operator overloading 🙂



  • CStoll schrieb:

    [...] wenn da jede Klasse ihre eigenen Flags hat, ist das Chaos vorprogrammiert.

    Im wahrsten Sinne des Wortes. 😃



  • Xin schrieb:

    CStoll schrieb:

    Es gibt kein Chaos, da Window sich genauso verhält, als wäre es mit Window::Flags implementiert worden.

    Du hast mir immer noch nicht verraten, was der Ausdruck 'wnd1&wnd2' für eine Bedeutung haben soll.

    Wenn operator & für zwei Fenster nicht deklariert ist, würde eine Hirachie hochgegangen und das Ergebnis wären übereinstimmende WindowFlags, genauso wie wnd1->Flags & wnd2->Flags.
    Wenn Dir das nicht gefällt, deklariere operator & als private member.

    Ist dir klar, daß du dadurch auch die (normal erlaubten) Aufrufe wie 'w&Window::FullScreen' wieder außer Gefecht setzt?

    CStoll schrieb:

    Windows enthalten WindowFlags und beide können im Bedarfsfall auf die Flags reduziert werden - ob das jetzt per MyWindow->Flags passiert, oder durch eine Typkonvertierung auf WindowFlags macht da keinen Unterschied.

    Du sagst "enthalten" - und das steht ehr für eine "hat-ein"-Beziehung. (btw, ein Fenster enthält auch seine Position, den Text der Titelleiste etc. - soll es dafür auch von Rect, String etc abgeleitet werden?)

    Das ist genau das, was man sich von wiederverwendbaren Klassen wünscht.

    In meinem Klassen gibt's keine Fenster, ich schreibe ja kein OS. Aber was die Titelleiste angeht, finde ich viele Parallelen bei meinen Klassen.
    Icons sind bei mir abgeleitet von u.a. BitMaps (die von Flächen abgeleitet sind) und Strings und Listenelementen und Punkten (Position), weil Icons haben Namen und weil Icons von Strings abgeleitet ist, darf Liste auch nach Namen suchen usw...

    Die Ableitung Bitmap->Icon kann ich ja noch nachvollziehen (wobei der Fall auch schon in Richtung der Rechteck/Quadrat-Problems gehen könnte), aber der Rest klingt für mich nach fehlverstandenem OOP.

    Wo ist das Problem? Ich sehe hier bisher vorrangig Vorteile.

    Was ist daran ein Vorteil, besonders kryptischen Code schreiben zu können?

    CStoll schrieb:

    Ich kann ja nichts dafür, wenn du meine Begründung nicht akzeptiert. Ein Fenster HAT Flags - und ist kein (aufgewertetes) Flag.

    Man kann sich vieles von verschiedenen Perspektiven ansehen. Ich würde mich an Deiner Stelle nicht so allgemeingültig festlegen.

    Nehmen wir nochmal als Kontrast das Auto-Beispiel - ein Auto HAT eine Farbe, aber IST (bestenfalls) ein färbbares Objekt. Genauso würde ich, wenn ich Vererbung nutzen wollte, eine Basisklasse Flagable verwenden, die Methoden SetFlag(), ResetFlag() und CheckFlag() anbietet (eventuell auch als Template).

    CStoll schrieb:

    Potentielle Fehlerquellen? Ist das jetzt einfach nur mal dahergeschrieben oder steckt da eine belegbare Befürchtung hinter?

    Du mußt alle deine Flag-Klassen identisch aufbauen - wenn du da eine Kleinigkeit vergisst, klappt es plötzlich nicht mehr so wie gewünscht. Und zeig mir mal, wie man die Flag-Klassen per Template erzeugen kann.

    Warum müsste ich die Flag-Klassen identisch aufbauen!?

    Was braucht man denn für eine Flag-Klasse? Die typbezogenen Operatoren und die Namen den Wert der Flags.

    Und Werte hinter den Flags, die sinnvolles Arbeiten erlauben (für "einfache" Flags sind nur Zweierpotenzen sinnvoll).

    Keine Ahnung, wo Du potentielle Gefahren siehst, aber wenn Du sie siehst, lass sie mich wissen.

    Siehe oben - schonmal versucht, was bei 'if(w&d)' herauskommt? Sowas ist weder besonders lesbar noch macht es irgendetwas sinnvolles - aber es wird anstandslos compiliert.[/quote]
    Deklariere es als private und es kompiliert nicht mehr. Es ist ja nicht so, als ob diese Sachen nicht möglich wären.
    [/quote]Wenn du den Operator in der Window-Klasse privat deklarierst, schaltest du damit auch den geerbten Operator aus (ich bin mir nicht ganz sicher, inwieweit das mit globalen Operatoren zusammenarbeitet), also mußt du vermutlich mehr machen als "nur" den Operator privat zu deklarieren.

    Hier stelle ich aber auch mal die Frage, ob das w&d wirklich interessant ist. Das hat genausowenig Sinn wie ( w->WindowFlags & d->WindowFlags ). Wozu soll das gut sein? Welche Frage soll das beantworten? Wenn beide Objekte mindestens eine beliebige Gemeinsamkeiten haben, dann...?

    Wenn ich 'w->WindowFlag&d->WindowFlags' schreibe, sehe ich was dahintersteckt - beim 'w&d' müsste ich erstmal überlegen (und eventuell sogar nachsehen).

    Derartige Abfragen kommen in meiner Programmierung äußerst selten vor und dann lässt sich das notfalls auch lesbar darstellen, indem man in diesem eher seltenen Fall dem Leser klarstellt, dass man auf WindowFlags rauswill.

    if( static_cast< WindowFlags & >( window ) & static_cast< WindowFlags & >( dialog ) ) ...
    

    Im alltäglichen Fall - und der ist mir im Alltag wichtiger - ist das nicht erforderlich.

    Du denkst aber auch daran, daß du nicht der einzige bist, der deine Flag-Klassen verwendet 😉 Und selbst wenn ich dir die nötige Disziplin zutraue, deine Kollegen werden bestimmt auf die Idee kommen, es kürzer zu schreiben.

    DEvent schrieb:

    window = WindowFlags::Fullscreen;     // Flag setzen 
    window = WindowMode::DoubleBuffering; // Mode setzen
    

    Ich finde die Syntax ziemlich elegant.

    Und dafür benötigt die Window-Klasse dann ein halbes Dutzend Zuweisungsoperatoren (und je tiefer du in die Hierarchie runtersteigst, desto mehr werden es ;)).

    Allerdings mal eine Frage, ist sowas moeglich:

    class MeineFlags { }
    
    class MeineErweitertenFlags : MeineFlags { }
    
    class Window : public MeineFlags, MeineErweitertenFlags {}
    

    Also kann ich MeineFlags erweitern, indem ich davon ableite? Muesste eigentlich gehen?

    technisch möglich, aber so hast du eine Mehrdeutigkeit, weil Window zwei MeineFlags-Subobjekte hat (einmal direkt und einmal indirekt in MeineErweiterten Flags).

    PS: Gut zu wissen, daß ich nicht alleine dastehe.



  • eine Window klasse von einer WIndowFlags klasse abzuleiten macht keinen sinn 👎

    ach ne moment sind ja eh alles kiddies hier also schnauze cstoll shade etc. 🤡 😋



  • ulfbulf schrieb:

    ach ne moment sind ja eh alles kiddies hier also schnauze cstoll shade etc. 🤡 😋

    Sagt wer? Wenn du uns beleidigen willst, dann bitte mit Namen und Anschrift.



  • CStoll schrieb:

    ulfbulf schrieb:

    ach ne moment sind ja eh alles kiddies hier also schnauze cstoll shade etc. 🤡 😋

    Sagt wer? Wenn du uns beleidigen willst, dann bitte mit Namen und Anschrift.

    merkst du nix 😕 🙄



  • CStoll schrieb:

    Nehmen wir nochmal als Kontrast das Auto-Beispiel - ein Auto HAT eine Farbe, aber IST (bestenfalls) ein färbbares Objekt. Genauso würde ich, wenn ich Vererbung nutzen wollte, eine Basisklasse Flagable verwenden, die Methoden SetFlag(), ResetFlag() und CheckFlag() anbietet (eventuell auch als Template).

    Ach ich weis nicht. Da die Operatoren ja nicht virtual sind und es im Grunde nichts vererbt wird, find ich das nicht so wichtig. Ist mehr ein Syntax-Sucker und hat weniger mit der OOA zu tun.

    CStoll schrieb:

    technisch möglich, aber so hast du eine Mehrdeutigkeit, weil Window zwei MeineFlags-Subobjekte hat (einmal direkt und einmal indirekt in MeineErweiterten Flags).

    Spielst eine Rolle, da die Flag-Klassen keine Felder und keine Methoden haben und von niemanden erstellt werden?
    Btw, von den einzelnen Flag-Klassen spezielle Flag-Klassen abzuleiten macht ja auch kein Sinn.

    Ich sehe in der Methode eher Vorteile:
    - Der Compiler entscheidet, wohin ein Flag genau gespeichert wird. Ich kriege eine groessere Transparenz, da ich einfach dem Objekt bestimmte Eigenschaften zuweisen kann, ohne spezielle Methoden ansprechen zu muessen.

    object = EigenschaftX;
    if ( object & EigenschaftX ) { /*...*/ }
    

    Die interne Implementation bleibt mir dabei verborgen, und das ist immer ein Vorteil.
    - Man hat Typsicherheit bei den Flags.
    - Ausserdem ist es eine kuerzere Schreibweise.



  • DEvent schrieb:

    CStoll schrieb:

    Nehmen wir nochmal als Kontrast das Auto-Beispiel - ein Auto HAT eine Farbe, aber IST (bestenfalls) ein färbbares Objekt. Genauso würde ich, wenn ich Vererbung nutzen wollte, eine Basisklasse Flagable verwenden, die Methoden SetFlag(), ResetFlag() und CheckFlag() anbietet (eventuell auch als Template).

    Ach ich weis nicht. Da die Operatoren ja nicht virtual sind und es im Grunde nichts vererbt wird, find ich das nicht so wichtig. Ist mehr ein Syntax-Sucker und hat weniger mit der OOA zu tun.

    Und mir ist die Flag-Klasse halt zu sehr übersüsst 😃

    CStoll schrieb:

    technisch möglich, aber so hast du eine Mehrdeutigkeit, weil Window zwei MeineFlags-Subobjekte hat (einmal direkt und einmal indirekt in MeineErweiterten Flags).

    Spielst eine Rolle, da die Flag-Klassen keine Felder und keine Methoden haben und von niemanden erstellt werden?
    Btw, von den einzelnen Flag-Klassen spezielle Flag-Klassen abzuleiten macht ja auch kein Sinn.

    Erstens hat die Flag-Klasse Datenmember (ihr Wert) und Methoden (die Flag-Operatoren) und zweitens tritt die Merhdeutigkeit schon dadurch auf, daß Window nicht mehr eindeutig zu einem Flag reduziert werden kann (das ist wichtig, um den Aufruf 'wnd&MeineFlags::Flag1' auflösen zu können).

    Ich sehe in der Methode eher Vorteile:

    Und ich sehe auch die Nachteile:
    - unintuitive Verwendung ( object=Eigenschaft ist zwar schön zu schreiben, aber der Anwender muß erstmal darauf kommen, was sich hinter dieser Zuweisung verbirgt)
    - Aufwand bei der Erweiterung (op& wird vererbt, wobei ich mir nicht ganz sicher bin, welche Operatoren der Compiler überhaupt in die Überladungsauflösung einbeziehen darf, op= muß die abgeleitete Klasse selber übernehmen (und das im Zweifelsfall für alle Flag-Klassen, die unterwegs aufgesammelt wurden).

    PS: Und Typsicherheit kann man auch auf anderem Weg erreichen 😉

    Edit @ulf: Ich merke, daß du ein Troll bist



  • CStoll schrieb:

    Edit @ulf: Ich merke, daß du ein Troll bist

    macht nix, vielleicht gibts in diesem foru ja doch noch andere leute die ironie verstehen 👍



  • Wir waren gerade dabei, eine schöne konstruktive Diskussion aufzubauen. Das mußt du jetzt nicht kaputtmachen, indem du versuchst, plumpe (und sinnlose) Zwischenbemerkungen zu machen - und nachträglich als "Ironie" zu deklarieren. Wenn du also nichts konstruktives beitragen kannst, dann halt lieber Abstand.



  • is ja gut is ja gut, wenn du die anspielung nicht verstehst ignorier sie halt einfach 🙄



  • DEvent schrieb:

    Ich sehe in der Methode eher Vorteile:
    - Der Compiler entscheidet, wohin ein Flag genau gespeichert wird. Ich kriege eine groessere Transparenz, da ich einfach dem Objekt bestimmte Eigenschaften zuweisen kann, ohne spezielle Methoden ansprechen zu muessen.

    object = EigenschaftX;
    if ( object & EigenschaftX ) { /*...*/ }
    

    Die interne Implementation bleibt mir dabei verborgen, und das ist immer ein Vorteil.

    Nein, das ist ein Trugschluss.
    Sag mir einfach ob folgender Code korrekt ist:

    window = Fullscreen;
    window = Border3D;
    

    Niemand kann es sagen. Ist Fullscreen und Border3D vom selben Flag-Typ? Wenn ja: böser Fehler, wenn nein dann funktioniert es.
    Es kompiliert anstandslos. egal was nun der Fall ist. Gefährliches Problem.

    Kann einem bei

    window.Mode = Fullscreen;
    window.DialogMode = Border3D;
    

    nicht passieren. Natürlich kann man außerhalb der Klasse ein Window::Fullscreen und Dialog::Fullscreen nutzen um so die wahrscheinlichkeit eines fehlers zu reduzieren - aber er ist gegeben und wahnsinnig schwer auffindbar. Und man muss sehr wohl wissen was ein Dialog Mode und was ein Window Mode ist - da ist nichts mit Transparenz. Genausowenig wie bei window.Mode und window.DialogMode.

    - Man hat Typsicherheit bei den Flags.

    Hat man ohne vererbung genauso.

    - Ausserdem ist es eine kuerzere Schreibweise.

    sobald das als argument genannt wird, sollten alle alarmglocken läuten.

    schreibfaulheit ist nie ein guter grund.

    Wir haben die Vorteile also auf genausoviele wie die window.Mode/window.DialogMode syntax reduziert.

    Dazu die Nachteile:
    total verwirrende Syntax und eigentlich genau ein Beispiel dafür warum manche Leute operator overloading verbieten wollen. operatoren werden umdefiniert und den ursprüngliche sinn wird nicht erhalten:

    window = a;
    window = b;
    
    &a == &b //false
    &window == &a //true
    

    das verwirrt jeden leser erstmal gehörig. es ist nämlich ein absolut unnatürliches verhalten.

    davon dass window keine flags ist sondern hat - ok, wir wissen ja wie verkorkst hier manche leute OOP sehen 😉

    Jede neue Flag-Klasse macht den Code noch mehr komplex. Mit 1 Klasse ist es nett, mit 2 ist es komisch und wird immer schlimmer je mehr Klassen dazu kommen.

    Es gibt abstruse fehlerquellen, wie zB eine Funktion die die Flags auslesen will: die bekommt dann gleich das ganze window-objekt. window & dialog ist ebenfalls ein abstruses problem.

    Die Frage ist: welchen Vorteil bringt vererbung dann hier? Ganz einfach: vererbung wird hier eingesetzt um schreibarbeit zu reduzieren. das ist der ganze vorteil dieser syntax - mehr nicht. wer dafür unlesbaren code produzieren will: bitte. aber dann sollte man auch sagen warum man es so macht und nicht irgendwelche komischen gründe finden warum diese syntax besser ist.



  • Shade Of Mine schrieb:

    Xin schrieb:

    Shade Of Mine schrieb:

    Wenn ich nun so dumm bin und die Flags von Windows und Dialog so trenne - dann habe ich das selbe Problem mit der "eleganten Syntax". Wenn Modal ein Flag von Dialog ist und Fullscreen einer von Dialog, dann ist sowas schon ziemlich dirty zu implementieren:

    win = Model | Fullscreen;
    

    natürlich möglich - aber dann wird die implementierung langsam häßlich.

    Sorry, das ist nicht möglich, da operator | ( WindowFlags &, DialogFlags & ) nicht definiert ist.

    Und genau das sind die Punkte die einen Anwender verwirren.

    Wenn ich

    win = Fullscreen;
    win = Modal;
    

    machen kann...

    Auch auf die Gewissheit hin, dass ich mich wiederhole: Es geht nicht...

    Shade Of Mine schrieb:

    man trennt die beiden Flags nicht also will ich eigentlich:

    win = Fullscreen | Modal;
    

    machen.

    Auch auf die Gewissheit hin, dass ich mich wiederhole: Es geht nicht...

    Warum antworte ich Deine Postings, wenn Du sie nicht liest!?

    Shade Of Mine schrieb:

    Aber auch dieser Beitrag geht nicht an Xin, sondern an etwaige leser.

    Und was sollen die damit anfangen!? Du kritisierst Dinge, die so nicht gehen, ergo auch nicht kritisiert werden können.

    Der einzige, der hier Leute verwirrt, bist Du, denn...

    DEvent schrieb:

    win = Fullscreen | Modal;
    

    Sowas waere echt cool, wenns denn moeglich waere...

    Auch auf die Gewissheit hin, dass ich mich wiederhole: Es geht nicht...
    DEvent, das wäre auch nicht cool, denn die Intention wäre hier nicht verwandte Datenobjete mit | zu verbinden. Und weil sie nicht verwandt sind, geht das auch nicht, also lass Dir von Shade keinen Unsinn einreden. Was Shade schreibt, hat nichts mit meinen Flag-Klassen zu tun, sondern mit Enums und genau die verwende ich nicht.

    Edit: Da Shade immernoch falschen Code verbreitet hier nochmal der richtige:

    win = WindowFlags::FullScreen;     // WindowFlags & WindowFlags::operator = ( WindowFlags const & ) - gibt's => geht
    win = WindowMode::Modal;           // WindowMode  & WindowMode ::operator = ( WindowMode  const & ) - gibt's => geht
    

    Zwei nicht verwandte Typen, die Shade hier mit | verbindet:

    win = WindowFlags::FullScreen | WindowMode::Modal; //  ??? & operator ???::operator | ( WindowFlags & const, WindowMode const & )  - Gibt's nicht => geht nicht
    

    Und nochmal: Du musst angeben, welchen Typ der Flag hat, darum ist es eindeutig. Ohne Typ, kein Flag. Darum hat der Code von Shade nichts mit meinen Flagklassen zu tun.

    CStoll schrieb:

    Xin schrieb:

    CStoll schrieb:

    Es gibt kein Chaos, da Window sich genauso verhält, als wäre es mit Window::Flags implementiert worden.

    Du hast mir immer noch nicht verraten, was der Ausdruck 'wnd1&wnd2' für eine Bedeutung haben soll.

    Wenn operator & für zwei Fenster nicht deklariert ist, würde eine Hirachie hochgegangen und das Ergebnis wären übereinstimmende WindowFlags, genauso wie wnd1->Flags & wnd2->Flags.
    Wenn Dir das nicht gefällt, deklariere operator & als private member.

    Ist dir klar, daß du dadurch auch die (normal erlaubten) Aufrufe wie 'w&Window::FullScreen' wieder außer Gefecht setzt?

    Nopes, ist mir nicht klar.
    operator & ( Window &, Window & ) fängt w&d ab, aber nicht w & WindowFlag::FullScreen.

    CStoll schrieb:

    Und dafür benötigt die Window-Klasse dann ein halbes Dutzend Zuweisungsoperatoren (und je tiefer du in die Hierarchie runtersteigst, desto mehr werden es ;)).

    Und? Sind alle eindeutig, werden vererbt und es gibt keine tausenden von Funktionen.

    CStoll schrieb:

    Allerdings mal eine Frage, ist sowas moeglich:

    class MeineFlags { }
    
    class MeineErweitertenFlags : MeineFlags { }
    
    class Window : public MeineFlags, MeineErweitertenFlags {}
    

    Also kann ich MeineFlags erweitern, indem ich davon ableite? Muesste eigentlich gehen?

    technisch möglich, aber so hast du eine Mehrdeutigkeit, weil Window zwei MeineFlags-Subobjekte hat (einmal direkt und einmal indirekt in MeineErweiterten Flags).

    PS: Gut zu wissen, daß ich nicht alleine dastehe.

    Man muss schon wissen, was man tut und dass die Flags nicht in einer Vererbungslinie stehen dürfen, weil sie sonst doppelt auftreten, ist wohl klar. Darum Templates, damit man eben nicht eine Vererbungslinie aufbaut.

    ulfbulf schrieb:

    eine Window klasse von einer WIndowFlags klasse abzuleiten macht keinen sinn 👎
    ach ne moment sind ja eh alles kiddies hier also schnauze cstoll shade etc. 🤡 😋

    Solange Du nicht Mann genug bist, mit einer erkennbaren Identität gegen mich zu trollen, so troll dich. Kritik gegenüber bin ich offen, derartige Pöpeleien machen aus dem Forum einen Kindergarten. Also werd erwachsen.
    Solltest Du derjenige IRC-Admin sein, der mich im #cpp mit der Begründung gebannt hat, weil er mich im Forum nicht mag und mich nicht aus dem Forum werfen kann, dann kann ich Dir nur sagen: Die Pubertät sollte mit 20 langsam abgeschlossen sein.



  • Shade Of Mine schrieb:

    Sag mir einfach ob folgender Code korrekt ist:

    window = Fullscreen;
    window = Border3D;
    

    Niemand kann es sagen. Ist Fullscreen und Border3D vom selben Flag-Typ? Wenn ja: böser Fehler, wenn nein dann funktioniert es.
    Es kompiliert anstandslos. egal was nun der Fall ist. Gefährliches Problem.

    Es kompiliert nicht, warum der Code eindeutig falsch ist, steht im Posting zuvor.

    Shade Of Mine schrieb:

    window = a;
    window = b;
    
    &a == &b //false
    &window == &a //true
    

    das verwirrt jeden leser erstmal gehörig. es ist nämlich ein absolut unnatürliches verhalten.

    Das Zweite ist false.

    Shade Of Mine schrieb:

    - Ausserdem ist es eine kuerzere Schreibweise.

    sobald das als argument genannt wird, sollten alle alarmglocken läuten.

    schreibfaulheit ist nie ein guter grund.

    Schreibfaulheit ist in Algorithmen ein sehr guter Grund, weil je weniger Blah-Text, desto mehr kann man sich auf den Algorithmus konzentrieren. Dafür nehme ich in Kauf, dass die Erstellung der Flags aufwendiger(!) ist.
    Schreibfaulheit selbst ist also nicht das Ziel der Flag-Klassen.

    Shade Of Mine schrieb:

    davon dass window keine flags ist sondern hat - ok, wir wissen ja wie verkorkst hier manche leute OOP sehen 😉

    Und wir wissen, dass manche Leute, andererleuts Postings nicht lesen oder nicht verstehen. 😉

    Dir gefällt die Idee nicht, das ist okay.
    Die Idee scheint mir von Dir noch nicht ganz verstanden zu sein. Es steht Dir frei das ganze mal auszuprobieren und auszutesten und es steht Dir auch frei dagegen zu sein. Deine Argumentation haben aber nichts mit den Flag-Klassen zu tun.



  • Xin schrieb:

    Auch auf die Gewissheit hin, dass ich mich wiederhole: Es geht nicht...

    Warum antworte ich Deine Postings, wenn Du sie nicht liest!?

    Alle meine Beispiele gehen sehr wohl - nicht immer 1:1 auf deinen Beispielcode bezogen, aber da du sowieso keinen kompletten Code gepostest hast ist sowas kaum zu vermeiden.

    DEvent schrieb:

    win = Fullscreen | Modal;
    

    Sowas waere echt cool, wenns denn moeglich waere...

    Auch auf die Gewissheit hin, dass ich mich wiederhole: Es geht nicht...

    Und auch das ist problemlos möglich.

    Nicht immer ist dein Code das einzig mögliche. Wenn man ein win = Fullscreen | Modal will, dann kann man es machen. Technisch absolut kein Problem. Aber es geht hier nicht um Technik.

    Edit: Da Shade immernoch falschen Code verbreitet hier nochmal der richtige:

    win = WindowFlags::FullScreen;     // WindowFlags & WindowFlags::operator = ( WindowFlags const & ) - gibt's => geht
    win = WindowMode::Modal;           // WindowMode  & WindowMode ::operator = ( WindowMode  const & ) - gibt's => geht
    

    Auch wenn es dich schockiert - ob man nun WindowFlags/WindowMode oder sonstwas qualifiziert - es bleibt ein a=b für den Leser.

    Zwei nicht verwandte Typen, die Shade hier mit | verbindet:

    win = WindowFlags::FullScreen | WindowMode::Modal; //  ??? & operator ???::operator | ( WindowFlags & const, WindowMode const & )  - Gibt's nicht => geht nicht
    

    Ich sehe 0 Probleme sowas technisch zu implementieren.

    Und nochmal: Du musst angeben, welchen Typ der Flag hat, darum ist es eindeutig. Ohne Typ, kein Flag. Darum hat der Code von Shade nichts mit meinen Flagklassen zu tun.

    Ob ich qualifiziere oder nicht ändert den Code kein bisschen. Mal abgesehen davon dass ich nicht immer qualifizieren _muss_ - zB in der Window Klasse drinnen.

    Wenn operator & für zwei Fenster nicht deklariert ist, würde eine Hirachie hochgegangen und das Ergebnis wären übereinstimmende WindowFlags, genauso wie wnd1->Flags & wnd2->Flags.
    Wenn Dir das nicht gefällt, deklariere operator & als private member.

    Mehr Code komplexität.

    Shade Of Mine schrieb:

    window = a;
    window = b;
    
    &a == &b //false
    &window == &a //true
    

    das verwirrt jeden leser erstmal gehörig. es ist nämlich ein absolut unnatürliches verhalten.

    Das Zweite ist false.

    Ja, mein Fehler. Die & muss man sich wegdenken, ich habe etwas daran herumgebastelt und da ist der Fehler reingerutscht.

    Da b ein Flag ist und somit keine Zuweisung stattfindet, auch wenn da ein op= war, führt das zu schwer zu verstehenden Code.

    Schreibfaulheit ist in Algorithmen ein sehr guter Grund, weil je weniger Blah-Text, desto mehr kann man sich auf den Algorithmus konzentrieren. Dafür nehme ich in Kauf, dass die Erstellung der Flags aufwendiger(!) ist.
    Schreibfaulheit selbst ist also nicht das Ziel der Flag-Klassen.

    Zeig mal bitte ein Beispiel wo Schreibfaulheit besser ist als sinnvolle Namen und Konventionen. Man verwendet deshalb ja auch "sort" und nicht "s" 😉
    Man hat vector<int>::iterator statt einen vector der sich wie ein iterator verhält 😉

    Und wir wissen, dass manche Leute, andererleuts Postings nicht lesen oder nicht verstehen. 😉

    Und manche Leute wollen nicht verstehen. Ja, das wissen wir.

    Dir gefällt die Idee nicht, das ist okay.
    Die Idee scheint mir von Dir noch nicht ganz verstanden zu sein. Es steht Dir frei das ganze mal auszuprobieren und auszutesten und es steht Dir auch frei dagegen zu sein. Deine Argumentation haben aber nichts mit den Flag-Klassen zu tun.

    Du ignorierst ja - genau wie bei der OOP Diskussion die Punkte die dir nicht gefallen.

    Ich habe die Idee durchaus verstanden - es erinnert mich an den Stack in Java. Erspart Schreibarbeit aber das war es auch schon.

    Auch wenn du es wieder ignorieren wirst:
    nenn mir mal die Vorteile von deiner Methode gegenüber nicht vererben.

    Schreibarbeit ist der einzige Vorteil. Es kann keinen anderen geben als Syntax weil es technisch gleichwertig mit "w->Mode" ist.

    Und genau diese Syntax kritisiere ich - auch wenn du die Kritik ignorierst. Das ist mir egal. Ich will nur nicht dass Leute wie DEvent dann prompt auf sowas "reinfallen" und nur die ersparte Schreibarbeit sehen.

    Es gibt eine Menge pitfalls die man beachten muss damit dein Code korrekt läuft. zB w&d ist etwas dass man sehr sehr leicht übersehen kann.

    Dazu eben die von mir genannten logischen Probleme die ich genannt habe.

    Mir ist durchaus klar wie praktisch diese ersparte Schreibarbeit ist. Aber da ersparte schreibarbeit das unwichtigste von allen Punkten ist, zieht das bei mir nicht so. Ich sehe vielmehr die ganzen Probleme, die ich ohne vererbung nicht hätte.

    PS:

    if(win) {
    }
    

    was genau macht das eigentlich?
    testet es ob das fenster in einem guten zustand ist? oder ist es der test auf flags?

    lässt sich alles natürlich definieren - aber wo bleibt die intuition?



  • Shade Of Mine schrieb:

    was genau macht das eigentlich?
    testet es ob das fenster in einem guten zustand ist? oder ist es der test auf flags?

    lässt sich alles natürlich definieren - aber wo bleibt die intuition?

    Intuition in C++ Operatorueberladung? Es ist genauso eine Gewoehnung wie in dem unterem Beispielcode, da sehe ich keinen Unterschied.

    std::string b = "b";
    std::string c = "c";
    std::string a = b + c;
    std::string a = b - c; // ???
    

    Xin hat eigentlich sehr wohl einen Code gepostet, gleich auf Seite 1, die MyClassFlags Klasse.

    Xin schrieb:

    Auch auf die Gewissheit hin, dass ich mich wiederhole: Es geht nicht...
    DEvent, das wäre auch nicht cool, denn die Intention wäre hier nicht verwandte Datenobjete mit | zu verbinden. Und weil sie nicht verwandt sind, geht das auch nicht, also lass Dir von Shade keinen Unsinn einreden. Was Shade schreibt, hat nichts mit meinen Flag-Klassen zu tun, sondern mit Enums und genau die verwende ich nicht.

    Ich meinte eigentlich das Fullscreen und Modal beide Flags sind. Sowas muesste doch gehen. Das man nicht verschiedene Typen miteinander mischen kann, ist logisch.

    window = WindowFlags::Fullscreen | WindowFlags::Modal.
    

    Xin schrieb:

    Man muss schon wissen, was man tut und dass die Flags nicht in einer Vererbungslinie stehen dürfen, weil sie sonst doppelt auftreten, ist wohl klar. Darum Templates, damit man eben nicht eine Vererbungslinie aufbaut.

    Man kann die FlagKlassen aber nicht final/sealed machen? Sonst geht das untere ja nicht. Das ist aber schlecht: Darf zwar von den Flag-Klassen keine speziellen Extended-Flag-Klassen machen, kann aber diese Flag-Klassen nicht gegen Vererbung schuetzen.

    class Window : public FlagClass { }
    

    Also was geht alles:

    window = Flags::Fullscreen; // weist dem Window den Flag Fullscreen zu
    window = Flags::Modal; // weist dem Window den Flag Modal zu
    window = Flags::Fullscreen | Flags::Modal; // weist dem Window beide Flags zu?
    if ( window & Flags::Fullscreen ) // testet, ob Window den Flag Fullscreen hat
    window = window2; // ??
    if ( window & window2 ) // ??
    if ( window ) // ??
    

Anmelden zum Antworten