Gültigkeitsbereich im Konstruktor
-
class test { public: test(); ~test(); private: IGUIElement _mainframe; }; // ... test::test() : _mainframe(this) { }Wobei ich jetzt mir aber grade nicht sicher bin, ob man this schon in der Initialisierungsliste verwenden darf (das Objekt ist ja noch gar nicht vollständig initialisiert). Ansonsten funktioniert die Variante von dir, per new angeforderter Speicher bleibt, bis er per delete freigegeben wird, und wenn das erst in ~test geschieht, lebt das Objekt eben auch so lange.
EDIT: zu spät...
-
Also kann ich eigentlich nichts verkehr machen wenn ich new und delete verwende?
Wenn ich bei ~test() vergesse delete aufzurufen, hab ich ein Speicherleck oder?
wenn ich delete IGUIELement aufrufe wird dann auch der Destruktor von IGUIElement aufgerufen?
MfG
Scarabol
-
Nein, ja, ja.
Verkehrt machen kannst du folgendes:
class test { public: test() { _mainframe = new IGUIElement(...); } ~test() { delete _mainframe; } private: IGUIElement *_mainframe; }; // ... int main() { test a, b; a = b; }Und schon hast du einen Crash. Warum? Weil bei der Zuweisung a = b der Zeiger _mainframe einfach stumpf kopiert wird. Am Ende der Funktion werden a und b zerstört, beide Destruktoren werden aufgerufen und auf den gleichen Zeiger wird 2 mal delete ausgeführt -> das geht schief. Um das zu verhindern musst du auch noch einen Zuweisungsoperator und einen Kopierkonstruktor definieren, die eine tiefe Kopie erzeugen. Google dazu auch mal nach der Regel der Großen Drei.
-
Cool danke an alle für die Hilfe jetzt weiß ich was ich wissen wollte.
MfG
Scarabol
-
ipsec schrieb:
Wobei ich jetzt mir aber grade nicht sicher bin, ob man this schon in der Initialisierungsliste verwenden darf (das Objekt ist ja noch gar nicht vollständig initialisiert).
Verwenden darf man es, man sollte nur Funktionsaufrufe etc. unterlassen, die auf diesen Speicher zugreifen (Der Zeiger an sich ist gültig, der Bereich dahinter aber noch nicht vollständig initialisiert).
-
Nur noch 2 kleine Ergänzungen, um das Bild abzurunden.
ipsec schrieb:
Nein, ja, ja.
Verkehrt machen kannst du folgendes:
class test { public: test() { _mainframe = new IGUIElement(...); } ~test() { delete _mainframe; } private: IGUIElement *_mainframe; }; // ... int main() { test a, b; a = b; }....auf den gleichen Zeiger wird 2 mal delete ausgeführt -> das geht schief. ...
+ er hat ein Speicherleck (das erste a::_mainframe wird nicht abgeräumt).
ipsec schrieb:
...Um das zu verhindern musst du auch noch einen Zuweisungsoperator und einen Kopierkonstruktor definieren, die eine tiefe Kopie erzeugen. ...
...oder die eine Kopie verhindern.
Gruß,
Simon2.
-
Scarabol schrieb:
Also kann ich eigentlich nichts verkehr machen wenn ich new und delete verwende?
Wie schon dargelegt wurde kannst du vieles verkehrt machen. Wie du deinen Mainframe als "richtiges" Member (also nicht als Pointer) verwenden kannst wurde ja schon gezeigt. Das ist deutlich sicherer und du kannst vieles nicht verkehrt machen.
-
Hi,
Nukularfüsiker schrieb:
Bin mir nicht sicher ob ich das Problem verstehe, aber ich glaube die Lösung heißt Initialisierungsliste.
class test { public: test(); ~test(); private: IGUIElement _mainframe; };test::test() : _mainframe(this) { }
Das funktioniert leider nicht weil:
error C2259: 'IGUIElement': Instanz von abstrakter Klasse kann nicht erstellt werdenMfG
Scarabol
-
Scarabol schrieb:
Das funktioniert leider nicht weil:
error C2259: 'IGUIElement': Instanz von abstrakter Klasse kann nicht erstellt werdenDas hat dann nichts mit der Entscheidnung pointer vs normaler Member zu tun, sondern damit, dass IGUIElement oder eine seiner Basisklassen eine pur virtuelle Methode enthält und nicht instantiiert werden kann (bzw. nur als Basisklassenobjekt einer Klasse, die die entsprechenden Methoden überschreibt). Die Fehlermeldung wäre dir auch bei der Variante "Pointer + new/delete" gekommen.
-
Alles klar danke an euch alle.
MfG
Scarabol