Konstante Memberfunktionen
-
Hallo, ich lese gerade das Buch "Einführung in die Programmierung mit C++" von Bjarne Strostrup jedoch verstehe ich was im Bezug auf die Konstanten Memberfunktionen nicht ganz.
#include <iostream> using namespace std; class date { public: int day() const ; int year(); }; int date :: day () const { return 14; } int date :: year() { return 2012; } void func ( date d , const date &obj ) { /*/ - Nicht konstantes Objekt kann konstante Funktion aufrufe. - Konstantes Objekt kann konstante Funktion aufrufen - Konstantes Objekt kann keine NICHT Konstante Funktion aufrufen. /*/ int a = d.day(); // Funktioniert int b = obj.day();// Funktioniert // int c = obj.year(); // Funktioniert nicht cout<<"a: " << a << endl; cout<<"obj: " << b << endl; } int main(int argc, char* argv[]) { date d; const date obj; func ( d , obj ); system("PAUSE"); }int c = obj.year(); <-- Das geht nicht weil der Compiler nicht wissen kann das day(); den Zustand von date nicht ändert. ( So steht es im Buch erklärt )
Wie kann den eine Funktion den Zustand eines Objektes ändern ?
Ich kann mir nicht vorstellen wie das gemeint ist. Kann mir jemand dafür vielleicht ein Beispiel geben?
-
"Zustand" = Membervariablen.
Eine konstante Methode garantiert, dass innerhalb dieser Methode keine Membervariablen des entsprechenden Objektes geändert werden1.
Wenn du nun ein konstantes Objekt hast, darfst du nur konstante Methoden dieses Objektes aufrufen - nur so ist gesichert, dass der Zustand des Objektes nicht geändert wird.
Felix
1 Ja, es gibt eine Ausnahme, die ich hier jedoch mutwillig unterschlage. Der interessierte Leser möge nach "mutable" googeln.
-
struct Date { private: int tag; int monat; public: void setTag(int neu) { tag=neu; } //Ändert den Status des Objekts //-> darf nicht const sein. void setMonat(int neu) const { monat=neu; } //Ändert den Status des Objekts //-> Kein const -> Compiler Fehler };
-
Hallo danke für euere Antworten. Aber 100% ig hab ich es noch nicht verstanden.

m = foo; // Funktioniert foo = m; // Funktioniert nicht, aber warum nicht? foo ist doch keine konstante#include <iostream> using namespace std; class date { private: public: int foo; int month(int) const ; date( int f ) : foo(f) {} }; int date :: month (int m) const { const var = 8; int var_2 = var; // Funktioniert // var = var_2; // Funktioniert nicht da var Konstant ist m = foo; // Funktioniert (Gibt hier 99 aus da der Konstruktor der Variable foo den Wert 99 zugewiesen hat) foo = m; // Compiler Fehler: const-Objekt kann nicht modifiziert werden. return m; } void func ( const date &obj ) { cout<< obj.month(5)<<endl; } int main(int argc, char* argv[]) { date obj(99); func ( obj ); system("PAUSE"); }
-
foo ist zwar keine Konstante, aber die Methode month() ist konstant. Somit dürfen innerhalb dieser Methode keine Member verändert werden. Und da foo ein Member ist, darf es nicht verändert werden.
-
Bei
int date :: month (int m) constbedeutet das const, dass keine Member veraendert werden duerfen waehrend dem Funktionsaufruf. Also auch jene Member nicht, die nicht als const deklariert wurden.
Bei
m = foo; // Funktioniert (Gibt hier 99 aus da der Konstruktor der Variable foo den Wert 99 zugewiesen hat) foo = m; // Compiler Fehler: const-Objekt kann nicht modifiziert werden.ist m eine lokale Variable, also kein Member. Deshalb darf sie veraendert werden. foo ist allerdings ein Member weshalb man foo nicht aendern darf.
-
Das Schlüsselwort const ist einfach eine Zusicherung seitens des Programmiers und der Compiler überprüft ob "Const-Correctness" gegeben ist.
Der Compiler behandelt durch const die Daten nicht anders! Es dient rein dem Programmierer.
Nimm dir mal als Beispiel sowas wie memset oder strlen, memcmp.Ein strlen möchte einen string und sagt dir wie lang er ist. Er verändert den Parameter nicht also ist er const. Somit weiß der Programmierer auch, dass der string vor und nach dem Aufruf gleich ist. Sowas wie ein Sicherheitsmechanismus.
Ein memset setzt einen Speicherbereich auf einen einheitlichen Wert. Wie sich hier vermuten lässt darf der Parameter nicht const sein, weil der Speicher ja überschrieben wird.Eine const-Methode einer Klasse bedeutet, dass das Objekt const bleibt, also der Speicher der Objekts nicht verändert wird. Somit können const-Methoden nur weitere const-Methoden des Objekts bzw. const-Methoden der Objekte der Klassen aufrufen.
void auswerten(const Klasse &readOnly) { // Ich will nur von readOnly etwas lesen mit z.B. gettern } void bearbeiten(Klasse &writeRead) { // Ich will hier sowohl lesen, als auch schreiben können } class C { void ichVeraendereMichNicht() const { cout << einMember; } void ichVeraendereMichNichtSchummeln() const { einMember = 4; } // autsch, ich und meine member sind doch const. Compiler meckert! void ichVeraendereMich() { einMember = 4; } // so ist es besser private: int einMember; };
-
Es gibt zwei Bereiche, in denen der Compiler das const überprüft:
a) Innerhalb der Methode
b) Beim Aufruf der Methode.Innerhalb der Methode schaut der Compiler, dass in const Methoden an den Membervariablen des Objekts nichts geändert wird. Schließlich heißt const "diese Methode ändert nichts an dem Objekt, auf dem sie aufgerufen wird", und der Compiler glaubt dir das nicht einfach sondern stellt das sicher, dass das auch stimmt. Andersrum schaut er aber nicht, ob eine non-const methode auch wirklich was ändert - auch wenn er das sicherlich könnte.
Beim Aufruf ist es andersrum: wird eine const-Methode aufgerufen, ist dem Compiler herzlich egal, auf was für einem Objekt das geschieht. Schließlich weiß er, dass die Methode das Objekt nicht verändert, also darf sie auf allen Objekten aufgerufen werden. Anders bei non-const Methoden: non-const Methoden dürfen nur auf objekten aufgerufen werden, die nicht als const deklariert sind, bzw. andersrum: auf Objekten, die als const deklariert sind, dürfen auch nur Methoden aufgerufen werden, die garantieren, dass das Objekt nicht geändert wird.
-
Also bei manchen Sachen frag ich mich, wieso es der Compiler nicht selber tuned? Getter Methoden, die Kopien liefern (sei es von primitiven Datentypen oder Objekten) sind immer const. Klar, muss ich ihm auf die Sprünge helfen, wenn ich eine Methode vector<stuff> &Klasse::getFatArray() habe, aber dass ich dann auch schon wieder die const Variante der Methode nochmal explizit hinschreiben muss, finde ich Wucher. Wieso sollte ich die const Variante unterschlagen? Probleme hat man dann wieder, wenn man das const Objekt von Typ Klasse den Aufruf von getFatArray() nicht zulässt, obwohl ich nur lesen will, nur weil ich so faul war und die const Methode nicht geimplt habe. Naja so ist das halt. Bei manchen Sachen könnte sich C++ ein Scheibchen von C# abschneiden. Bei Java ist das aber der gleiche Müll. Ich erfinde meine eigene Progsprache, euere Kinder werden sie dann lernen müssen, weil alles darauf basiert

-
Du kannst die nonconst-Version meist über die const-Version implementieren. Wenn du ganz schreibfaul bist, kannst du das in ein Makro stecken.