PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : was hat dieses const hier zu bedeuten?


Vedek Bareil
2002-12-06, 22:03:20
Hallöchen,

ich beschäftige mich gerade mit einem C++ Programm, das in der Deklaration einer Klasse LVec die folgende Zeile double & operator()(long i) const; enthält, mit der entsprechenden Definition double & LVec:: operator()(long i) const {
assert( i >=0);
assert( i <=nDim);
return *(v +i);} Der Hintergrund ist, daß LVec Vektoren kapselt und der Operator () die i-te Komponente des Vektors zurückgibt. Was ich aber nicht so ganz verstehe ist, was das const am Ende der Zeile zu bedeuten hat. Trifft meine Vermutung zu, daß es bedeutet, daß der Operator keine der Eigenschaften des LVec-Objektes verändern darf?

zeckensack
2002-12-06, 22:12:09
Originally posted by Vedek Bareil
Trifft meine Vermutung zu, daß es bedeutet, daß der Operator keine der Eigenschaften des LVec-Objektes verändern darf? Genau das isses :)

IMO ist der Code aber 'broken', er sollte "double const &" als return type haben. Eben weil er verspricht daß er das Objekt nicht ändert. Meiner Ansicht nach muß das auch für die Benutzer der Methode gelten, man kann immer noch eine nicht-const Variante schreiben (bei const/nicht const können Methoden sogar anhand des Rückgabetyps überladen werden, was ja sonst nicht erlaubt ist).

Demirug
2002-12-06, 22:13:32
Das mit dem const hat folgenden zweg.

Es besteht bei C++ die möglichkeit einer Funktion eine Konstante Referenz auf ein Object zu übergeben.


void TestFunc (const LVec& vec)
{
}


Für eine solche Referenz dürfen jetzt nur noch Methoden aufgerufen werden welche diesen const vermerk haben. Versucht man andere Methode aufzurufen bekommt man einen Compilerfehler.

Für die Methode selbst ändert sich nichts. Man kann also weiterhin auch Eigenschaften verändern. Dies sollte man aber nicht tun weil es dem Prinzip von const wiederspricht. Das es vom Compiler aber nicht generel verboten ist hat einen grund. Manchmal schreibt man Klassen welche Eigenschaften haben welche zu Zwischenspeichern von Aufwendigen Berechnungenergebnissen benutzt werden. Beim ersten Aufruf der Methode wird die Rechnung durchgeführt bei allen weiteren Aufrufen wird das gespeicherte Ergebniss zurückgegeben. Da eine solche Methode ja durchaus const sein kann (sie verändert ja eigentlich den Zustand des Objektes nicht) muss man auch in const methoden Eigenschaften verändern dürfen.

Vedek Bareil
2002-12-10, 01:48:43
Originally posted by zeckensack
Genau das isses :)

IMO ist der Code aber 'broken', er sollte "double const &" als return type haben. Eben weil er verspricht daß er das Objekt nicht ändert. Hehe, es kommt ja noch besser! :)
Zwar darf innerhalb der Operatordefinition das Objekt nicht verändert werden, aber wenn der Operator die i-te Komponente (besser gesagt: eine Referenz auf diese) erst einmal zurückgegeben hat, dann soll es durchaus erlaubt sein, diese zu ändern. Sei z.B. a ein Vektor, dann sollen Zuweisungen der Form a(2)=3 möglich sein.
Daß innerhalb der Operatordefinition keine Veränderung des Objektes vorgenommen werden darf, hängt damit zusammen, daß die Klasse LVec friend-Funktionen wie diese hier hat:

// -------------------------------------------------------
// operation v2 =v1 * lambda, v1 is vector, lambda is scalar
// -------------------------------------------------------
LVec operator*(const LVec & v1,double lambda)
{
LVec v2(v1.nDim);

for (long i1 =1;i1<=v1.nDim;i1++){
v2(i1) =v1(i1) *lambda;
}
return v2;
}

Wegen dem const im Argument darf der Operator * den Vektor v1 nicht verändern, und weil in der Operatordefinition von * der Operator () als Methode von v1 aufgerufen wird, muß der Compiler davon überzeugt werden, daß auch () keine Veränderung an v1 vornimmt. Und diese Überzeugungsarbeit wird durch das hinten an stehende const in der Deklaration von () geleistet.

KiBa
2002-12-10, 23:57:43
Originally posted by Demirug
Das mit dem const hat folgenden zweg.

Es besteht bei C++ die möglichkeit einer Funktion eine Konstante Referenz auf ein Object zu übergeben.


void TestFunc (const LVec& vec)
{
}


Für eine solche Referenz dürfen jetzt nur noch Methoden aufgerufen werden welche diesen const vermerk haben. Versucht man andere Methode aufzurufen bekommt man einen Compilerfehler.

Für die Methode selbst ändert sich nichts. Man kann also weiterhin auch Eigenschaften verändern. Dies sollte man aber nicht tun weil es dem Prinzip von const wiederspricht. Das es vom Compiler aber nicht generel verboten ist hat einen grund. Manchmal schreibt man Klassen welche Eigenschaften haben welche zu Zwischenspeichern von Aufwendigen Berechnungenergebnissen benutzt werden. Beim ersten Aufruf der Methode wird die Rechnung durchgeführt bei allen weiteren Aufrufen wird das gespeicherte Ergebniss zurückgegeben. Da eine solche Methode ja durchaus const sein kann (sie verändert ja eigentlich den Zustand des Objektes nicht) muss man auch in const methoden Eigenschaften verändern dürfen.

ich kann dir nicht ganz folgen, meinst du etwa sowas hier? (ungetestet) :

class test
{
public: void t() const { i = 1; }
private: int i;
};

das ist sehr wohl vom compiler generell verboten, da die const- member funktion das entsprechende objekt nicht verändern kann. falls das mit deinem compiler geht, schmeiß ihn weg... ;)

dein beispiel mit dem zwischenspeichern ist aber natürlich wichtig, dafür wurde auch das schlüßelwort mutable eingeführt; msdn:
"This keyword can only be applied to non-static and non-const data members of a class. If a data member is declared mutable, then it is legal to assign a value to this data member from a const member function."
und so gehts:

class test
{
public: void t() const { i = 1; }
private: mutable int i;
};

imo sollte man const durchgehend und konsistent einsetzen, überall, wo etwas logisch konstant ist!

Demirug
2002-12-11, 07:28:24
KiBa, du hast recht nach der ganz alten C++ definition war sowas irgendwann mal erlaubt. Inzwischen geht es nicht mehr.