Getter



  • Damit das funktioniert

    void f(const x& X)
    {
        size_t l = X.GetLength();
    }
    

    Const-Correctness



  • mit folgendem code:

    size_t GetLength ( ) const { return length }
    

    ist die methode konstant.
    konstante methoden können keine member inerhalb der klasse verändern und nur ebenfalls konstante methoden aufrufen.

    hierbei würde der compiler z.b. zwei fehler melden:

    class x
    {
    private:
    int _a;
    void foo() { };
    void bar() const { };
    
    public:
    void something ( ) const 
    {
      _a = 5; //fehler, something darf keine membervariable verändern
    
      this->foo(); //fehler, foo ist keine konstante methode und
                   //kann daher nicht von something aufgerufen werden.
    
      this->bar(); //ok, bar ist ebenfalls eine konstante methode und kann von 
                   //something aufgerufen werden.
    }
    };
    

    im anderen fall den du gepostet hast:

    const size_t GetLength ( ) { return length } ;
    

    wird eine methode deklariert, welche eine konstante variable vom typen size_t zurück gibt.
    also nicht die methode ist konstant sondern der rückgabetyp.



  • Wobei noch erwähnt werden muß, daß das "const" als Rückgabetyp überflüssig ist (solange es sich nicht um eine Referenz handelt):

    size_t GetLength ( ) const { return length; }
    
    // bzw.
    
    const size_t& GetLength ( ) const { return length; }
    

    (P.S: Das Semikolon muß innerhalb der geschweiften Klammern!)

    Da im ersten Fall sowieso der Wert kopiert wird, ist dieser ja automatisch konstant (d.h. kann nicht verändert werden).
    Nur bei einer Referenz ist es wichtig, ob man das "const" hinzufügt oder nicht.



  • Es gibt aber durchaus eine Daseinsberechtigung für konstante Rückgabetypen.

    class x
    {
    public:
    	operator bool() 
    	{
    		return v != 0;
    	}
    	void operator+=(x & other)
    	{
    		v += other.v;
    	}
    	size_t v;
    };
    
    const x operator+ (x lh, x& rh) // <-- gibt const x zurück
    {
    	lh+=rh;
    	return lh;
    }
    
    int main()
    {
    	x a,b,c;
            ...
    	if (a + b = c)
    	{
    		std::cout << "whoa";
    	}
    	return 0;
    }
    

    Dieses Beispiel würde ohne konstanten Rückgabewert wunderbar kompilieren, aber mit Sicherheit nicht das tun was es soll.



  • Nein, dein Beispiel funktioniert weder mit noch ohne const (für die Zuweisung muß ein sog. L-Value vorliegen, d.h. z.B. eine nicht-konstante Referenz).



  • Doch das läuft. Habs grad nochmal probiert. Das steht auch irgendwo ganz vorne in effective c++.



  • Das ist völlig in Ordnung. Das ist ein temporäres Objekt, welches einfach nur in genau dem Ausdruck, indem er gebraucht wird lebt. Es ist ein völlig korrekte L-Value.



  • Ok, habe es gerade mal mit verschiedenen Compilern getestet.
    Beim Borland C++ Builder 5 kam die von mir erwartete Fehlermeldung "No L-Value" (ich weiß, ist schon ein älterer Compiler).
    Aber sowohl MSVC 2003 als auch 2005 haben die Non-Const-Version jeweils fehlerfrei kompiliert (sogar bei einer Funktion anstatt einem Operator).

    Kann mir vllt. jemand den Paragraphen im C++ Standard nennen? (weil ich sehe darin einfach keinen Sinn - und ich werde auch weiterhin Rückgabewerte von Wertetypen ohne "const" deklarieren!)

    In "Effective C++" unter "Item 21" steht zwar auch, daß man "const" bei den Operatoren von benutzerdefinierten Typen verwenden soll, aber nicht warum dies generell erlaubt wird.

    Bei nichtkonstanten Referenzen als Parameter werden ja auch keine temporären Objekte erlaubt.

    Und ich hatte vor kurzem in einem Beitrag noch geschrieben, daß C++ vollkommen logisch sei -)



  • Das müsste irgendwo bei temporären Objekte in Ausdrücken sein. Atm kann ich nicht nachschauen, aber das solltest du schon finden. (irgendwo bei expressions)

    Hmm. Ich dachte, dass in Effective C++ erklärt steht, warum das so gemacht werden sollte. Muss auch mal noch nachschauen..



  • drakon schrieb:

    Das ist ein temporäres Objekt, welches einfach nur in genau dem Ausdruck, indem er gebraucht wird lebt. Es ist ein völlig korrekte L-Value.

    Speziell ist hier eben, dass es sich nicht um ein LValue handelt.

    C++-Standard, 3.10 schrieb:

    5 The result of calling a function that does not return a reference is an rvalue. User defined operators are functions, and whether such operators expect or yield lvalues is determined by their parameter and return types.

    10 An lvalue for an object is necessary in order to modify the object except that an rvalue of class type can also be used to modify its referent under certain circumstances.

    Im Weiteren hat camper einmal ziemlich ausführlich gegen Operatoren mit const -qualifiziertem Rückgabetyp argumentiert. Hier wäre sein Beitrag zu sehen.



  • Nexus schrieb:

    drakon schrieb:

    Das ist ein temporäres Objekt, welches einfach nur in genau dem Ausdruck, indem er gebraucht wird lebt. Es ist ein völlig korrekte L-Value.

    Speziell ist hier eben, dass es sich nicht um ein LValue handelt.

    Hmm, Ok. Ich habe den Begriff nicht vorsichtig genug benutzt, aber dass man das Objekt verändern darf man ja.


Anmelden zum Antworten