const-Methoden
-
Hi,
ich dachte... ich hätte das Konzept verstanden. Soweit ich weiß dürfen in const-Methoden keine Membervariablen verändert werden u. aus diesem Grund auch keine (nicht-const)Methoden aufgerufen werden.
Jetzt scheint es aber noch eine andere Eigenart zu geben. Der Compiler spuckt mir hier folgende Fehlermeldung (an den fett markieren stellen im Code) aus:
error C2440: 'return': 'const float [2]' kann nicht in 'float *const ' konvertiert werden
[code="cpp"]
class Grundstueck {
private:
float Ecke1[2];
float Ecke2[2];
public:
Grundstueck(float x1=0,float y1=0,float x2=0, float y2=0);
float * const get_Ecke1() const;
float * const get_Ecke2() const;
...};
Grundstueck::Grundstueck(float x1, float y1, float x2, float y2){
Ecke1[0]=x1; Ecke1[1]=y1;
Ecke2[0]=x2; Ecke2[1]=y2;
}
float * const Grundstueck::get_Ecke1() const{
return Ecke1;
}
float * const Grundstueck::get_Ecke2() const{
return Ecke2;
}[/code]
Kann mir einer erklären was hier genau passiert ?
-
Da darfst du nur ein
const floatzurückgeben, ansonsten kann man die Membervariable über den Zeiger verändern, was dann nicht der Sinn der Sache einer const-Methode ist.
-
Außerdem wäre eine Point-Klasse o. ä. hier angebracht, die einen einzelnen Punkt repräsentiert. Vielleicht boost::tuple oder std::pair.
-
Wobei sich die Fehlermeldung darauf bezieht, daß
float * constundfloat const *(aliasconst float *) verschiedene Dinge sind.
-
Du gibst dort ein "const pointer to float" zurück, du solltest aber ein "pointer to const float" zurückgeben. (const float* bzw. float const*, nicht aber float *const. Pointer zeigen immer auf den Typen links vom

-
Irgendwie stehe ich jetzt total auf dem Schlauch... ich bin gerade ein bisschen am testen.
Ich hab das ganze jetzt erstmal so belassen:
float * const Grundstueck::get_Ecke1(){ return Ecke1; }Hier gebe ich ja einen konstanten Zeiger auf meinen float Member zurück... nehmen wir mal an ich wöllte diesen Zeiger manipulieren (was hier nicht funktionieren sollte). Wie würde ich das überhaupt anstellen? So wie ich es kenne landet der zurückgegebene Wert in einer neuen Variablen z.B.
float * p; p=g.get_Ecke1(); p=p+1;Damit wäre das ganze doch hinfällig

-
Nein, du verstehst es nicht. Lies meinen Beitrag noch mal genau. Dass man den Pointer verändern kann, interessiert niemanden, weil es nichts in der Klasse ändert. Das hier
struct foo { int i_; int bar() const { return i_; } };Ist auch kein Problem, auch wenn das int nicht const ist. Aber wer das int verändert, verändert nichts am Objekt. Du brauchst also, wie schon geschrieben, keinen konstanten Pointer, sondern einen Pointer auf ein konstantes Objekt.
-
John D schrieb:
Ich hab das ganze jetzt erstmal so belassen
Und somit bleibt der Fehler wie er ist ist...
Dein
returnpaßt nicht zur Signatur deiner Methode.
-
Hm...
ok d.h. schonmal.... in dieser Variante hat das "const" keinen praktischen Nutzen?
typ * const bsp(){ ... }
-
Nein. Genau so wie
const int foo();Nicht besonders sinnvoll ist.
-
John D schrieb:
in dieser Variante hat das "const" keinen praktischen Nutzen?
Nicht nur hat es keinen Nutzen, es wird vollkommen ignoriert.
typ * const bsp();ist genau die gleiche Signatur wie
typ * volatile bsp();und
typ * bsp();
-
Sehr gut... sehr gut
Ich habe gerade mal vollkommen auf das "const" verzichtet und über den Pointer den Member verändert.
Wundert mich nur, das unser Dozent diesen getter in der Musterlösung auch ohne "const" definiert hat:
C++:
class Grundstueck {
private:
float Ecke1[2];
float Ecke2[2];Das bricht doch mit der Kapselung oder liege ich da falsch?
-
da hat was gefehlt:
class Grundstueck { private: float Ecke1[2]; float Ecke2[2]; public: Grundstueck(float x1=0,float y1=0, float x2=0, float y2=0); float *get_Ecke1(); float *get_Ecke2(); void set_Ecke1(float, float); void set_Ecke2(float, float); float Flaeche(); };
-
Ob es die Kapselung bricht ist wohl Ansichtssache, aber in jedem Fall sind die Setter so leicht sinnlos.

-
Jep

Ich denke ich habs verstanden. Danke dir/euch.
-
praktiker schrieb:
John D schrieb:
in dieser Variante hat das "const" keinen praktischen Nutzen?
Nicht nur hat es keinen Nutzen, es wird vollkommen ignoriert.
typ * const bsp();ist genau die gleiche Signatur wie
typ * volatile bsp();und
typ * bsp();nein. Das sind durch aus unterschiedliche Signaturen. Top-level cv-Qualifikation wird nur bei Parametern ignoriert.
Allerdings geht ein cv-Qualifikation des Rückgabetyps beim Funktionsaufruf verloren, wenn dieser Typ ein Skalar ist.
-
Ob es die Kapselung bricht ist wohl Ansichtssache
Ähh, es bricht eindeutig die Kapselung. Die Funktion get_Ecke1() ist wohl das Paradebeispiel wie man es nicht machen sollte. Damit kann man herliche Sauereien wie folgendes machen:
int main () { Grundstueck g; float* f; f = g.get_Ecke1(); *f = 1; f++; *f = 2; // Och woher weis ich denn dass ein Grundstück keine 3D Punkte als Grenze hat ? f++; *f = 3; // Och wir wollen aber double Koordinaten setzen double* f2; f2 = (double*) g.get_Ecke1(); *f2 = 5; }Effetive C++ Regel:
1.) Baue deine Klassen so dass sie einfach zu bedienen aber schwer zu missbrauchen sind.
2.) Gebe niemals eine Referenz, ein Zeiger auf interne Dinge zurück, wenn es eine Kopie auch tut.
-
Noch eine Schweinerei ist mir da eingefallen.
int main () { Grundstueck* g = new Grundstueck; float* f; f = g->get_Ecke1(); delete g; *f = 1; f++; }
-
cooky451 schrieb:
C++ ist auch scheiße, guck mal!
*((void*)0)Das kompiliert auch nicht.
-
@Bitte ein Bit
Es ist immer noch Schwachsinn, auch wenn ein Mod den Beitrag gelöscht hat.@komplimat
Ja, es geht um's Prinzip.