Ctor wird nicht aufgerufen???
-
Ich habe ein Problem, das entweder ein mir unbekanntes "Feature" von C++ ist oder ein MSVC-Bug.
Ich habe eine Klassenhirarchie und dummerweise wird der Ctor einer Klasse beim zweiten Instanzieren nicht aufgerufen. Bsp.:
// panel class panel : public base_panel { native_panel *m_panel; public: panel(base_pabel &parent) : base_panel(parent) { create(); } ~panel() { delete m_panel; } private: void create() { m_panel = new native_panel(); } }; // root_panel class root_panel : public base_panel { // Implementierung ist ähnlich vom obigen panel };So, soweit OK?
int main() { root_panel myroot; panel p1( myroot ); panel p2( p1 ); // Ctor wird nicht aufgerufen, und somit auch nicht create! }Gut.... und bei der Instanzierung von p2 wird der Ctor einfach nicht aufgerufen.
Hinzu kommt, das p2.m_panel den gleichen Wert wie p1.m_panel hat!!! D.h. die zeigen auf die gleiche Speicheradresse!
Das ganze ist mir überhaupt erstmal aufgefallen, weil als der Dtor von p2 aufgerufen wurde, das deleten von p2.m_panel einen Runtime-Error erzeugt hat (ein Assert). Weil das native_panel logischerweise schon im p1-Dtor gelöscht wurde. (zeigten ja beide auf das gleiche Objekt)Vielleicht war es gestern abend auch schon zu spät, aber das ist mir unbegreiflich.
Ich hab dann create() public gemacht und das probiert:
panel p1( myroot ); panel p2( p1 ); // Ctor wird nicht aufgerufen p2.create(); panel p3( p1 ); // Ctor wird nicht aufgerufenDer direkte create-Aufruf hat natürlich alles so gemacht, wie es sein soll. Aber p3.m_panel hat wieder auf die gleiche Adresse wie p1.m_panel gezeigt, weil der p3-Ctor nicht aufgerufen wurde.
Hab ich irgendwas verpasst? Oder ist das ein möglicher Bug im MSVC8 (mit SP)? Dann verschiebt diesen Thread bitte ins MFC-Forum.
-
Ich denke, panel könnte einen Copykonstruktor vertragen. Der automatisch generierte tut nicht das, was du willst.
-
Yep, der copy c'tor wird hier automatisch generiert und hat vorrang. Is aber kein Bug, is bei gcc genau das gleiche Verhalten.
-
Hem, mir ist nicht verständlich, warum hier der Copy-Ctor benötigt wird? Jedenfalls kopiere ich nicht bewusst ein panel... Oder kann es daran liegen, das der Ctor als Parameter den gleichen Basistyp haben will?
Werde aber heute abend das ganze trotzdem implementieren.
-
Artchi schrieb:
int main() { root_panel myroot; panel p1( myroot ); panel p2( p1 ); // Ctor wird nicht aufgerufen, und somit auch nicht create! }Die letzte Zeile wird vom Compiler für eine Funktionsdeklaration gehalten. Ändere das nach
panel p2( (p1) ); // .. aber jetztoder
panel p2 = p1;Gruß
Werner
-
Werner Salomon schrieb:
Die letzte Zeile wird vom Compiler für eine Funktionsdeklaration gehalten.
Grund? p1 ist doch kein Typ.
-
Artchi schrieb:
Hem, mir ist nicht verständlich, warum hier der Copy-Ctor benötigt wird? Jedenfalls kopiere ich nicht bewusst ein panel...
Oh! - da hätte ich Dir aber mehr zugetraut. Natürlich kopierst Du das panel mit
panel p2( p1 );'p2' ist eine Kopie von 'p1'. Außerdem hast Du mit mit
~panel() { delete m_panel; }einen nicht trivialen Konstruktor. Da gilt es die "Regel der Drei" zu beachten. Du musst Dich also auch noch um Kopy-Konstruktor und Zuweisungs-operator kümmern. Du kannst sie einfach private machen; aber machen musst Du was.
Gruß
Werner
-
LordJaxom schrieb:
Grund? p1 ist doch kein Typ.
.. erklären kann ich es mir auch nicht. Aber der Compiler VC8 tut es und der gcc anscheinend auch.
Gruß
Werner
-
Ich hatte auch alternativ versucht das ganze dynamisch per new zu instanzieren. War auch nicht besser. Denke es liegt tatsächlich am Copy-Ctor.
Zu folgendem:
panel p2 = p1;Hem... gefällt mir.
Der Compiler hatte auf Warnlevel 4 tatsächlich einen Assignment-Operator empfohlen. Ich sollte wirklich auf den Compiler hören und immer auf Level 4 compileren. (Ob er einen Copy-Ctor empfohlen hatte, muß ich heute abend nochmal nachschauen)
-
Oh! - da hätte ich Dir aber mehr zugetraut. Natürlich kopierst Du das panel mit
Yo, bin selber verwundert. Bin halt doch zu lange als Javaner unterwegs, wo ich jetzt endlich zu Hause mal wieder was richtiges in C++ angehe. Naja... that's racing.

-
Artchi schrieb:
Hem, mir ist nicht verständlich, warum hier der Copy-Ctor benötigt wird? Jedenfalls kopiere ich nicht bewusst ein panel...
Vermutlich nicht bewußt, aber trotzdem kopiert der Aufruf
panel p2(p1);(@Werner: Nein, das wird nicht als Funktionsdeklaration angesehen) den Inhalt von p1 nach p2).Oder kann es daran liegen, das der Ctor als Parameter den gleichen Basistyp haben will?
Es liegt daran, daß die Klasse zwei Konstruktoren hat - dein
panel(base_panel& parent);und den per Default erzeugten Copy-Ctorpanel(const panel& src);- und beim Anlegen von p2 passt letzterer besser auf die Parameter (die Umwandlung von T nach const T& hat höhere Priorität als die Umwandlung in die Basisklasse). Eine Lösung könnte es sein, den Copy-Ctor selber geeignet zu definieren (aber damit zerstörst du vermutlich die Semantikder Klasse an anderen Programmstellen), als Alternative kannst du einen Cast nehmen, um den richtigen Ctor zu erzwingen oder (du weichst auf das named-Construktor-idiom aus).panel p2(dynamic_cast<base_panel&>(p1));
-
ARGH! CStoll! Jetzt hat es bei mir Click gemacht!

An panel(const panel& src); hab ich überhaupt nicht gedacht!
Kein Wunder für das Verhalten! Und das Casting macht es mehr als deutlich! 
Danke für die Aufklärung!

-
Hä? Wurd nicht bereits gesagt das der copy c'tor angelegt wird? panel( base_panel& ) ist ja kein Ersatz für den copy c'tor.
-
CStoll schrieb:
panel p2(dynamic_cast<base_panel&>(p1));Ist ein dynamic_cast hier nicht overkill? Ein static_cast sollte reichen, da p1 ja in jedem Fall ein base_panel ist.
-
Werner Salomon schrieb:
Artchi schrieb:
int main() { root_panel myroot; panel p1( myroot ); panel p2( p1 ); // Ctor wird nicht aufgerufen, und somit auch nicht create! }Die letzte Zeile wird vom Compiler für eine Funktionsdeklaration gehalten. Ändere das nach
panel p2( (p1) ); // .. aber jetztoder
panel p2 = p1;Gruß
Werner.. Äh - da habe ich ja völligen Quatsch geschrieben

Das liegt am fehlenden Copy-Ctor wie ja inzwischen schon festgestellt wurde. Ich hatte es ausprobiert, und meinte bei der Klammerung ein anderes Verhalten bekommen zu haben. Aber das stimmte nicht.Gruß
Werner
-
david_pb! Ja, wurde. Danke auch den anderen.
Nur hab ich wirklich den panel-Parameter-Typ nicht vor Augen gehabt! *schäm* Ist mir erst nach CStolls Post bewusst geworden. Aber spätestens heute abend, wenn ich mich an die Implementierung des Copy-Ctors gemacht hätte, wäre es mir wie Schuppen von den Haare gefallen. 
CStoll! Das Named-Ctor-Idiom ist echt guter Hinweis!