Klasse vs. Pointer?
-
Hallo Leute,
ich habe da folgendes Problem:classA.hpp:
class ClassA : public ClassB { // ... ClassC C; // ... }
Beim Aufruf des Konstruktors von ClassA wird ja dann der Konstruktor von ClassB aufgerufen.
Auf dem "Rückweg" wird bei mir dann anscheinend implizit der Konstruktor von ClassC aufgerufen, in dem die Zeile "m_set = NULL;" eine Variable von ClassB überballert, die mir dann in ClassA fehlt.Jetzt habe ich das mal so geändert und das Problem war weg :
classA.hpp:
class ClassA : public ClassB { // ... ClassC* C; // ... }
classA.cpp:
ClassA::ClassA():ClassB() { C = new ClassC(); //.... } ClassA::~ClassA() { delete C; }
Und dann natürlich die Aufrufe der Memberfunktionen von C überall mit "->" statt ".".
Meine Frage ist, ob das jetzt einen konkreten C++-technischen Grund hat, warum das eine funktioniert und das andere nicht, oder ob ich lediglich durch veränderte Speichernutzung den eigentlichen Fehler überdecke.
Wäre dankbar für Antworten.
Gruss,
Qweety.
-
habe es nicht verstanden
-
class ClassA : public ClassB { // ... ClassC C; // ... }
Achtung !
ClassC C;
Was passiert da wohl ?
Du erstellst eine eine Variable statisch, sobald deine ClassA erzeugt wird, im Konstruktor ... und ClassC verhaelt sich eben wie erwartet, es ruft genau bei diesem erzeugen den "default constructor" auf .... Und eine instanz von ClassC existiert nun froehlich und munter als lokale Variable in deinem Konstruktor, bis das der Tod ... aehm bis der Scope deiner Definition endet ... sprich der Konstruktur von CLassA zu ende ist ... dann wird CLassC natuerlich auch Fachmaennisch zerlegt, sprich der destruktor deinner ClassC aufgerufen und die Instanz zerstoert ....mit
ClassC* C;
verhinderst du das nur ... du legst nun eine Variable vom Typ "Pointer auf ClassC" (intern eine Adresse, meist 32 bit gross) an, die auf irgendwas, nur nix nutzbares zeigt. Fuer die Ordnungsgemaesse benutzung bist nu selber verantwortlich ... sprich wenn du eine Instanz der ClassC erzeugst und C Zuweist
C = new ClassC()
musst die auch wieder zestoeren irgendwo ...
Aber aufpassen, dein Zeiger C ist natuerlich nur im Konstruktor gueltig ... also musst ClassC im Konstruktor von CLassA wieder Zerstoren, oder die dynamisch erzeugte Klasse ClassC mittels nen Zeiger anderswo bekannt machen, das du sie anderswo auch zerstoeren kannst ...Prinzipiell: es sind alles gangbare Wege, es haengt davon ab was du machen willst ... und das beschreibst in deinem Post ned. ALso kann dir auch keienr sagen was richtig und was falsch ist ...
ciao ...
-
Sehe keinen wesentlichen Unterschied zwischen den beiden Varianten: Beidemale wird der Konstruktor von ClassC aufgerufen; bei der ersten implizit, bei der zweiten explizit.
-
XYZ: Wieso soll C eine lokale Variable im Konstruktor sein?
-
Ack mist, sorry, hab uebersehen das es nicht der Konstruktor sondern deine Klass definition ist ....
Es aendert sich folgendes ...
dein C ist Membervariable, also solange gueltig wie die Instanz von A existiert ...
ClassC wird erzeugt bevor der Konstruktor von CLass A aufgerufen wird ...
ClassC wird zerstoert, nach dem desturktor von CLassA ausgefuehrt wurde und bevor class A endgueltig zerstoert wid ....Ciao ...
-
weil ich Bloedsinn gelesen habe
sah fuer mich aus wie ClassA::ClassA anstatt ClassA : public ClassB ...@Qweety
DU solltest mehr von dem Problemn posten ... weil so pauschal Aussagen ueber statische Mebers vs. dynamische Members sich ned machen lassen ....und dass mit dem Variablen uberschreiben "m_set = NULL;"
Wie kann der Konstruktor von CLassC ne Variable von CLassB "uberballern" ???ciao ...
-
und dass mit dem Variablen uberschreiben "m_set = NULL;"
Wie kann der Konstruktor von CLassC ne Variable von CLassB "uberballern" ???Hi nochmal,
das ist ja grad mein Problem.
ClassC hat mit ClassA und ClassB eigentlich nichts weiter zu tun, ausser dass eine Instanz davon in ClassA Membervariable ist.Wir der Konstruktor von ClassC implizit aufgerufen (erste Fassung), dann bekomme ich später im Programm einen Fehler, weil mir besagte Variable im Speicher kaputt geschrieben wurde (Debuggen führte zu der Erkenntnis, dass es im Konstruktor von ClassC passierte und m_set ist eine private Variable von ClassC, hat also eigentlich auch nix mit ClassA oder ClassB zu schaffen ).
Wähle ich die Pointer-Variante und rufe den Konstruktor via "new" auf, passiert das nicht.
Vielleicht ist es auch einfach ein Compiler-Fehler oder sowas. Solche Speicherfehler sind ja oft wie die Suche nach der Stecknadel im Heuhaufen.
Oder kann es auch sein, dass der eigentliche Fehler ganz woanders passiert und ich jetzt lediglich den Speicher etwas umstrukturiert habe, so das es zufällig nicht mehr "knallt"?
Ich persönlich habe immer gedacht, es sei so, wie Krösus es schon sagte:
Sehe keinen wesentlichen Unterschied zwischen den beiden Varianten: Beidemale wird der Konstruktor von ClassC aufgerufen; bei der ersten implizit, bei der zweiten explizit.
... und ich habe auch nichts anderes gefunden.
Aber nach diesem Effekt dachte ich mir, ich frage mal bei Euch nach, weil vielleicht einer von Euch ne andere Info hat. Man lernt ja schliesslich nie aus, gell .
Also erstmal danke für Eure Antworten .
Gruss,
Qweety.
-
der Unterschied ist, dass bei der Version "Membervariable" der Konstruktor von C zwischen den Konstruktoraufruf von ClassB und ClassA geschieht, bei der Version mit dem Zeiger geschieht es im Konstruktor von ClassA.
ClassA::ClassA () : ClassB(), C() {} //<-probier das mal
ist was anderes als
ClassA::ClassA () : C(), ClassB() {}