Referenzen auf private data members


  • Mod

    Ich bin auf sowas gestoßen:

    void machwas(int & a){a=5;}
    
    class klasse{
    private:
      int i;
    public:
      int & operator()(){return i;}
    };
    
    int main(){
      klasse k;
      machwas(k());  // setzt k.i auf 5
    }
    

    Irgendwie sehe ich den Sinn davon nicht. Wenn man eine Referenz zurückgibt, könnte man schließlich gleich i public machen, da man nicht mehr kontrollieren kann, was mit i geschieht. Übersehe ich da was?



  • Hi,

    ich sehe das genauso wie Du.
    Natürlich kann man über so eine "get-Referenz-Funktion" noch sowas wie Reference-Counting machen (und immerhin sind Referenzen nicht so leicht kopierbar wie Zeiger), aber mir fällt jetzt kein Szenario ein, bei dem das o.g. Konstrukt wirkliche Vorteile hätte.

    Gruß,

    Simon2.



  • SeppJ schrieb:

    ...Wenn man eine Referenz zurückgibt, könnte man schließlich gleich i public machen, da man nicht mehr kontrollieren kann, was mit i geschieht. Übersehe ich da was?

    Ohne konkreten Code würde ich dir recht geben. Es könnte vielleicht Ausnahmefälle geben (um Beispielsweise einen Operator [][] zu simulieren...), dies sollte aber wie gesagt die Ausnahme, nicht die Regel sein.


  • Administrator

    Simon2 schrieb:

    ..., aber mir fällt jetzt kein Szenario ein, bei dem das o.g. Konstrukt wirkliche Vorteile hätte.

    std::string str("jello");
    str[0] = 'h';
    

    Gut, das ist nicht ganz das Gleiche. Aber SeppJ hat die Sache so aus dem Kontext genommen, da ist es schwer zu sagen, ob es sinnvoll ist oder nicht.

    Grundsätzlich sind zwei Dinge zu sagen:
    1. Getter und Setter sind immer besser als public Attribute, auch wenn die Getter mal eine Referenz zurückgeben. So kann man immerhin prüfen, wo und wann ein Zugriff darauf erfolgt. Eine Rückgabe einer Referenz ist oft nicht so optimal, kann aber sinnvolle Zwecke habe.
    2. Der Missbrauch einer Schnittstelle zu verhindern ist zwecklos, das kann man nicht schaffen und darauf sollte man auch nicht hinarbeiten. Ich nehme mal das Beispiel des std::string .

    std::string str("jello");
    char& c = str[0];
    str.append(" world!");
    c = 'h';
    

    Der Kompilier schluckt dies, aber das Verhalten ist undefiniert. Man könnte sowas tatsächlich verhindern, nur ist es unnötig kompliziert.

    Grüssli


  • Mod

    Der gesamte Kontext wäre wohl etwas zu unübersichtlich. Die Klasse dient hauptsächlich als ein Wrapper für einen double-Wert mit ein paar Extras. Ich vermute der obige ()-Operator dient hier vor allem der Bequemlichkeit. Auf diese Weise ist der Zugriff auf das interessante Element immer schön knapp und übersichtlich.

    Zumindest ist es keine von den hier vorgeschlagenen Möglichkeiten, daher meine Vermutung.


Log in to reply