const member und operator=
-
Hi,
ich wollte eine const Membervariable deklarieren, wie z.B. in diesem Minibeispiel:
class AClass { private: const int m_constMember; public: AClass(const int val) : m_constMember(val) {}; }; // ... AClass a = someMethodThatReturnAnAClassObject();Leider mault dann der Compiler, dass ein operator= nicht verfügbar ist (weil er ja wahrscheinlich die const-Variable nicht zuweisen kann). Aber ich kann dies auch selber nicht, wenn ich einen Zuweisungsoperator implementiere, irgendwie so:
class AClass { // ... inline AClass& operator=(const AClass& other) { m_constMember = other.m_constMember; return *this; ; };Wie macht man das bloß. Sowas muss doch gehen?!?!
Viele Grüße,
Felix
-
Hallo,
der Zuweisungsop geht ja von einem existierenden Objekt aus. Das const Member hat zu diesem Zeitpunkt z.B. den Wert 5, für IMMER, ist ja konstant.
D.h. hier ist eine erneute Zuweisung über den op= nicht sinnvoll bzw. zulässig.MfG
GPC
-
"const" heißt, daß das Element nicht geändert werden kann. Da kannst du dich noch so sehr auf den Kopf stellen, der Compiler lässt dich diesen Wert nicht mehr ändern.
(aber eigentlich sollte der obere Ausschnitt so funktionieren - der braucht nicht den op=, sondern den Copy-Ctor (und der funktioniert mit const-Membern)).
-
Jaja, aber wie kann ich denn eine Membervariable einführen, die sich nach Erzeugung NIE mehr ändert? Die z.B. von der Konstellation der im Konstruktor übergebenen Parameter abhängt?
Mal als doofes Beispiel das Geschlecht einer Klasse Person. Wenn man Geschlechtsumwandlungen zunächst einmal nicht zulässt, gibt's entweder Jungens oder Mädchen. Und wenn Mutter und Vater auf die Idee kommen, ein neues Objekt zu (er)zeugen, hätte das im Konstruktor z.B. nen Parameter Geschlecht. Die Membervariable könnte und sollte folglich const sein. Aber dann kann ich das Kind nichtmehr irgendwie zuweisen.
Zugegeben, das hinkt etwas bei Personen und Kindern, aber ist klar, was ich meine??
-
Sorry, der Beitrag bezog sich auf GPC. Da war ich wohl beim schreiben zu langsam
-
Hmm, bei mir klappt das nicht. Allerdings auch mit nem struct. liegt's daran? Ich muss wohl mal ein größeres Beispiel geben:
typedef struct _CurvatureInfo { const float MinPrincipalCurvature; _CurvatureInfo(const float minPrincipalCurvature = 0.0f) : MinPrincipalCurvature(minPrincipalCurvature) { }; }CurvatureInfo; // ... class CUtils { public: inline static CurvatureInfo CreateCurvature(/* some parameters */) { // some calculations return CurvatureInfo(calculatedValue); }; }; // .... // SomeClass.cpp void SomeClass::method() { //... CurvatureInfo* curvatures = new CurvatureInfo[num]; for(int i = 0; i < num; i++) { curvatures[i] = CUtils::CreateCurvature(/* the parameters */); } }Puh. Und in der for-Schleife mault der Compiler. Ich hoffe, der Code ist schlüssig. Habe ihn ziemlich zusammengestutzt.
-
Also entweder du setzt dein Attribut als Pseudo-Konstante (d.h. du sorgst dafür, daß niemand bewußt den Wert ändert) oder du lebst damit, die Objekte nicht zuweisen zu können (es macht ja auch wenig Sinn, einen existierenden Menschen zu überschrieben - und genau das wäre die Semantik hinter dem op=) und reichst nur Zeiger auf deine Objekte herum.
Edit: Und bei deinem Code-Beispiel wäre es eine gute Idee, STL-Container zu verwenden (und per push_back() mit Werten zu füllen).
-
FelixManke schrieb:
Jaja, aber wie kann ich denn eine Membervariable einführen, die sich nach Erzeugung NIE mehr ändert? Die z.B. von der Konstellation der im Konstruktor übergebenen Parameter abhängt?
Mit const ändert sich nie was.
Um auf dein Beispiel zu verweisen:
class Person { public: enum Geschlecht {M, W}; private: const Geschlecht g; //Keine Zuweisungen möglich Person& operator=(const Person&); public: Person(Geschlecht g_) : g(g_) {} // Ctor Person(const Person &p) : g(p.g) {} //Copy Ctor ~Person(); //Dtor Geschlecht getGeschlecht() const { return g; } }; //... Person me(Person::M); //Männlich Person you(me); //ebenfalls männlich, über Copy Ctor Person x(Person::W); you = x; //nix da, op= gesperrt, Geschlechtsumwandlungen sind böse.Klaro?

MfG
GPC
-
Du kannst durchaus auch const member haben. Du musst sie nur zum richtigen Zeitpunkt (Konstruktor) initialisieren:
CPerson.h:
#include <string> class CPerson { private: const int m_geschlecht; std::string m_name; public: CPerson(int Geschlecht, std::string Name); int getGeschlecht(); std::string &getName(); };CPerson.cpp:
#include "CPerson.h" CPerson::CPerson(int Geschlecht, std::string Name): m_geschlecht(Geschlecht), m_name(Name) { // All in initalizers } int CPerson::getGeschlecht() { return m_geschlecht; } std::string &CPerson::getName() { return m_name; }Main.cpp:
#include "CPerson.h" #include <iostream> int main(int argc, char **argv) { int dummy = 0; CPerson Sohn(1, "Peter"); CPerson Tocher(0, "Marianne"); std::cout << "Sohn Name: " << Sohn.getName() << " Geschlecht: " << Sohn.getGeschlecht() << std::endl; std::cout << "Tocher Name: " << Tocher.getName() << " Geschlecht: " << Tocher.getGeschlecht() << std::endl; std::cin >> dummy; }
-
Hmm, aber wie mache ich das in meinem konkreten Fall? Ich kann da ja schlecht einen Copy-Konstruktor benutzen, wenn ich das Ergebnis einfach von einer Methode entgegennehme. Und nen anderen Konstruktor kann ich auch nicht aufrufen.
-
Noch mal zur genaueren Erklärung:
curvatures[i] = CUtils::CreateCurvature(/* the parameters */);Hier wird intern der Zuweisungsoperator (=) deiner Klasse aufgerufen.
Da diese aber ein konstantes Member enthält, kannst du diesen Operator ja nicht verwenden (und der Compiler erzeugt auch keine Default-Implementation hierfür).Wenn du wirklich diese konstante Member behalten willst, mußt du mit Zeigern arbeiten, d.h. z.B.
inline static CurvatureInfo* CreateCurvature(/* some parameters */) { // some calculations return new CurvatureInfo(calculatedValue); // <-- hier new verwenden }; CurvatureInfo** curvatures = new CurvatureInfo*[num]; for(int i = 0; i < num; i++) { curvatures[i] = CUtils::CreateCurvature(/* the parameters */); }Und beim Zerstören des Arrays, dann
for(int i = 0; i < num; i++) { delete curvatures[i]; } delete [] curvatures;
-
Ok, Danke. Aber wenn Pointer und Heap die einzige Möglichkeit sind, lasse ich das const vielleicht einfach weg -- macht die Sache einfacher :-).
-
FelixManke schrieb:
Hmm, aber wie mache ich das in meinem konkreten Fall? Ich kann da ja schlecht einen Copy-Konstruktor benutzen, wenn ich das Ergebnis einfach von einer Methode entgegennehme. Und nen anderen Konstruktor kann ich auch nicht aufrufen.
Natürlich kannst du:
class Person { //wie oben }; Person foo() { Person p(Person::M); return p; } Person x = foo();Klappt doch

MfG
GPC
-
Das ist doch, sofern ich richtig schaue, derselbe Code, wie in meinem echten Beispiel mit der Curvature.
Ne Klasse (Person bzw. CurvatureInfo) mit nem const Member,
nen Konstruktor, wo dieser Member initialisiert wird,
ne Methode (einer anderen Klasse - foo() bzw. CUtils::CreateCurvature()), die ein neues Objekt erzeugt und
ne (lokale) Variable (einer dritten Klasse), die dieses Objekt empfängt (Person x bzw. curvatures[i]).Warum klappt das denn bei mir nicht?
-
FelixManke schrieb:
Das ist doch, sofern ich richtig schaue, derselbe Code, wie in meinem echten Beispiel mit der Curvature.
Keine Ahnung, hab deinen Code nicht gelesen.
Ne Klasse (Person bzw. CurvatureInfo) mit nem const Member,
nen Konstruktor, wo dieser Member initialisiert wird,nem Copy-Ctor und nem privat deklarierten op=.
Die Person x wird per Copy-Ctor mit dem Objekt, welches foo zurückgibt, initalisiert. Scharf, heh?

MfG
GPC
-
Oh sorry,
da habe ich vorhin nicht genau genug geguckt und das mit dem operator= übersehen
. Sorry.Scharf ist's wirklich. Wieso gibt sich denn der Compiler plötzlich damit zufrieden, wenn er GAR keinen Zuweisungsoperator mehr hat. Wie kommt der denn auf die Idee, plötzlich den Copy-Konstruktor zu nehmen?! Sonderbar....
-
Hallo GPC,
dein Beispiel entspricht aber nicht dem von FelixManke,
da du den Copy-Konstruktor bei "Person x = foo()" aufrufst, während
wie ich auch schon geschrieben habe, bei FelixManke's Programm der Zuweisungsoperator aufgerufen wird, d.h.Person x; x = foo();wird auch NICHT funktionieren!!!
-
Th schrieb:
Hallo GPC,
dein Beispiel entspricht aber nicht dem von FelixManke,
behauptete ich ja auch nicht

da du den Copy-Konstruktor bei "Person x = foo()" aufrufst, während
wie ich auch schon geschrieben habe, bei FelixManke's Programm der Zuweisungsoperator aufgerufen wird, d.h.Person x; x = foo();wird auch NICHT funktionieren!!!
korrekt...
FelixManke schrieb:
Scharf ist's wirklich. Wieso gibt sich denn der Compiler plötzlich damit zufrieden, wenn er GAR keinen Zuweisungsoperator mehr hat. Wie kommt der denn auf die Idee, plötzlich den Copy-Konstruktor zu nehmen?! Sonderbar....
...dazu folgendes Beispiel:
std::string s(""); //Ctor std::string s2(s); //Copy-Ctor std::string s3 = s; //Copy-Ctor, oha. std::string s4; s4 = s; //Zuweisungs operatorMfG
GPC