Design-Frage: private-Zugriff bei einer Property-Klasse simulieren



  • Vertexwahn schrieb:

    Nur eine Frage am Rande: Woher kommt eigentlich der Bezeichner foo? immer wieder werden in Beispielprogrammen solche Bezeichner verwendet - hat das irgendeinen Grund?

    foo



  • keiner eine Idee oder Meinung?



  • Ich würde Lösung 2 hernehmen und leicht abwandeln. Würde als weiteren
    Parameter vllt noch eine Owner Klasse angeben, die direkten Zugriff haben
    kann, ... friend class Owner; ...
    (Die langsam recht vielen Template Parameter kann man ja eh teilweise
    mit template-Typedefs, bzw Workarounds dafür umgehen .. zum Beispiel bleibt
    die Owner Klasse ja auch eine Klasse lang gleich).

    Könnte mir das also irgendwie so vorstellen ...

    template<typename T, ...., class Owner>
    class property {
    private:
        T& directAccess() 
        { return data; }
    
    public:
        friend class Owner;
    };
    
    class Demo {
    public:
        property<int, setter, getter, Demo> data;
    
        void moppelkotze() 
        {
            data.directAcces() = 100;
        }
    };
    

    Vielleicht hilfts 🙂

    edit:
    Seh grad du hast eh (Member-)funktion geschrieben, also bereits auf sowas angedeutet ..



  • das mit dem friend class Owner geht leider nicht 😞 . An so etwas hatte ich natürlich auch schon gedacht, dass wär aber zu leicht gewesen 🙂



  • Also Variante 1 gefällt mir irgendwie nicht. Dann kannst du auch gleich die getter/setter als normale Memberfunktionen machen und übergibst dem property den this Zeiger. Zudem kannst du nicht davon ausgehen, dass du immer Member-Variablen zum getten/setten hast. Vor kurzem hab ich ein paar GUI Klassen gemacht, und da war es recht praktisch, wenn die getter/setter des propertys direkt mit OS spezifischen Funktionen arbeiten konnten.
    Variante 2 gefällt mir ehrlich gesagt auch nicht, weil 1. der Syntax-Zucker von properties dadurch verlorengeht und 2. das irgendwie nach unschönem Workaround aussieht.
    Ich hab dazu aber auch noch 'ne Frage. Wieso verpackst du die getter/setter in 'ner nested class? Ich hatte dann immer das Problemm, dass ich auf die Member der umschliessenden Klasse (in welcher dann auch das property definiert ist) nicht zugreifen konnte. Wenn ich das richtig mitbekommen hab, ist das wohl mittlerweile in den C++ Language Defect Report aufgenommen. Wie hast du das Problem gelöst?



  • property war doch diese tolle erfindung, die sich wie ein objekt verhält, aber kein objekt sein muss,sondern nur die kapselung irgendeines geters/seters sein konnte, oder?

    wenn ich richtig liege, so darf ein property eh nicht an ein objekt gebunden sein, da das property ja auch einen abstrakten wert, wie zb die länge eines vectors darstellen kann:

    vector v;
    //...
    double length=v.length;//abstrakter wert berechnet aus sqrt(x*x+y*y+z*z)
    v.length=1;//vector auf die länge eins bringen, wieder eine abstrakte berechnung
    

    daraus schließe ich, dass das objekt hinter der property(falls so eins existiert), innerhalb der Klasse liegen sollte, und das property nur die erscheinung nach aussen repräsentiert.

    hier ein beispiel:

    class Foo{
        private:
            int internalBar;
            int barGetter(){
                return internalBar;
            }
            void barSetter(int newBar){
                internalBar=newBar;
            }
        public:
            Foo():bar(functor(this,barGetter),functor(this,barSetter)){}
            property<int> bar; 
    };
    

    wie gesagt, dieser vorschlag trifft nur zu, wenn meine obere definition richtig ist, ansonsten bitte milde walten lassen 😃



  • @otze und groovemaster
    Die Problematik, die ihr ansprecht wird bei mir dadurch umgangen, dass es neben den Get- und Set-Policys auch noch eine Storage-Policy gibt, die sich um die Verwaltung des Objektes kümmert, so wär es also möglich auch otzes Ansatz zu realisieren.

    Ich glaub ich muss das intern noch ein wenig verzahnen, um es praktisch nutzbarer zu machen. Ich werde am Wochenende mal meine Arbeiten vorstellen.



  • aber wie willst du mithilfe dieser storage policie eine interaktion der einzelnen properties erreichen?



  • ja, daran arbeite ich noch, das meinte ich mit Verzahnung *g*. Irgend wie brauchen die Getter und Setter ja einen Hinweis auf die instanziierte StoragePolicy. Schade, dass es kein has_function<Klasse,Funktion> gibt 😉



  • kingruedi schrieb:

    Ich glaub ich muss das intern noch ein wenig verzahnen, um es praktisch nutzbarer zu machen. Ich werde am Wochenende mal meine Arbeiten vorstellen.

    Da bin ich mal gespannt. Ich arbeite nun schon seit einiger Zeit an einer Property Klasse und hab bisher zwar was für mich brauchbares aber noch nichts zufrieden stellendes hinbekommen.



  • Schade, dass es kein has_function<Klasse,Funktion> gibt

    solange es ein isDerived gibt, ist das kein problem.
    property muss einfach von StoragePolicy erben.

    //edit hmm wie wollt ihr eigentlich komplexere objekte darstellen?
    wollt ihr nur zugriff über den op-> erlauben? der op. ist ja nicht erlaubt(leider).



  • otze schrieb:

    //edit hmm wie wollt ihr eigentlich komplexere objekte darstellen?
    wollt ihr nur zugriff über den op-> erlauben? der op. ist ja nicht erlaubt(leider).

    Solche Sachen sind imo noch ziemlich komplex. Zumindest hab ich noch keine zufrieden stellende Lösung gefunden. Nur mal so als Beispiel, gegeben sei folgender Typ

    struct point
    {
        int x;
        int y;
        point(int x_, int y_)
            : x(x_)
            , y(y_)
        {
        }
    };
    

    Davon erstellen wir uns nun ein Property

    property<point, setter, getter> position;
    

    Sobald wir folgende Sachen machen

    position = point(0, 0);
    point tmp = position;
    

    ist alles ok, da die getter/setter aufgerufen werden. Was ist aber mit folgendem

    position.x = 10;
    int tmp = position.y;
    

    ?
    Das funktioniert erstmal nur, wenn das property von point erbt. Und selbst dann werden keine getter/setter aufgerufen, sondern einfach stur die x/y Member benutzt. Damit sowas richtig funktioniert, müsste point wie folgt aussehen

    struct point
    {
        property<int, setter_x, getter_x> x;
        property<int, setter_y, getter_y> y;
        point(int x_, int y_)
            : x(x_)
            , y(y_)
        {
        }
    };
    

    Natürlich kann man keine bestehenden Datentypen einfach so anpassen. Abhilfe könnten hier Template Typen schaffen. Dann wird aus T=int halt einfach T=propety<int, ...>. Ich denke allerdings, dass auch sowas einige schwer zu lösende Probleme hat. Aber vielleicht weiss king ja schon mehr.



  • wollt ihr nur zugriff über den op-> erlauben? der op. ist ja nicht erlaubt(leider).

    Ich biete den op-> an, der op. funktioniert nur für konstante Methoden bei mir!

    Der op-> liefert ein temporäres Objekt zurück, dass intern eine Kopie der StoragePolicy enthält, die einmal via Getter bearbeitet wurde und wenn das Objekt geändert wurde, dann wird es am Ende der Lebenszeit des temp-Objekts via des Setters zurückkopiert.



  • kingruedi schrieb:

    Ich werde am Wochenende mal meine Arbeiten vorstellen.

    Warum hast du es nicht veröffentlicht. Ich wäre sehr interessiert mir das ganze mal anzuschauen.



  • habe mir nur kurz die Problemstellung durchgelesen,
    vielleicht suchst du Slüsselwort friend



  • @Moppelkotze
    Ein paar Design und andere Probleme haben das verschoben, aber ich werd das noch dieses Jahr fertig stellen.

    @leo aka qsch
    Nein, dass kann man nämlich mit Template-Parametern nicht benutzen.



  • Warum eigentlich? (Nervt mich auch)



  • kingruedi schrieb:

    @Moppelkotze
    Ein paar Design und andere Probleme haben das verschoben, aber ich werd das noch dieses Jahr fertig stellen.

    Cool, freue mich schon drauf 😉 .



  • ness schrieb:

    Warum eigentlich? (Nervt mich auch)

    weil es jedwede kapselung ad absurdum führen würde


Anmelden zum Antworten