2012-06-19 11 views
5

Ich habe eine Basisklasse namens Panel, wo einige Informationen über ein Fenster gespeichert ist, dann habe ich Unterklassen für alle Steuerelemente: Button, Label usw. In der Basisklasse habe ich die virtual void ApplySchemeSettings(Scheme* scheme) { } Methode , die innerhalb des Panel(Panel* parent) Konstruktors aufgerufen wird. Aber statt der Unterklasse wird der ApplySchemeSettings aus der Basisklasse (Panel) aufgerufen.Virtuelle Methode nicht aufgerufen

class Panel 
{ 
    [...] 

public: 
    virtual void ApplySchemeSettings(Scheme* scheme) { }; 

    Panel(Panel* parent) 
    { 
     [...] 

     this->ApplySchemeSettings(scheme()); 
    }; 
} 

class Frame : public Panel 
{ 
    [...] 

public: 
    void ApplySchemeSettings(Scheme* scheme) 
    { 
     this->border = scheme->GetBorder("FrameBorder"); 
    } 
} 

Ich kann nicht erklären ApplySchemeSettings als abstraktes, weil die Unterklassen von Benutzern erstellt.

+1

'this-> ApplySchemeSettings (scheme());' der Typ von 'this' Zeiger an der Stelle des Aufrufs ist' Panel * const', also es ruft 'Panel :: ApplySchemeSettings' auf. Die Moral der Geschichte ist nie Aufruf virtueller Funktion vom Konstruktor der Basisklasse. –

+0

http://stackoverflow.com/questions/6582239/avoiding-virtual-methods-in-constructor –

+0

http://stackoverflow.com/questions/507043/virtual-function-invocation-from-constructor –

Antwort

8

Innerhalb eines Konstruktors verhalten sich virtuelle Funktionen nicht wie erwartet. Insbesondere jeder Aufruf einer virtuellen Funktion innerhalb eines Konstruktors löst immer den Aufruf der Version der Funktion auf, die in der aktuellen Klasse deklariert ist. Der Grund dafür ist, dass während der Objekterstellung eine Klasse konstruiert wird, indem zuerst die Basisklasse konstruiert wird, dann ihre Kindklasse, dann ihre Kindklasse usw. Folglich werden während der Objektkonstruktion die abgeleiteten Klassen erst bei der Basis initialisiert Klassenkonstruktoren werden beendet. Wenn Sie in der Lage wären, eine virtuelle Funktion aufzurufen und sie zur abgeleiteten Version innerhalb eines Basisklassenkonstruktors auflösen zu lassen, würden Sie eine Methode für eine Klasse aufrufen, die noch nicht initialisiert wurde - nicht einmal die Standardeinstellung Konstruktoren für die Datenmitglieder wären noch nicht aufgerufen worden.

Sie müssen einen anderen Ansatz zur Lösung dieses Problems finden. Sie können zum Beispiel eine zweistufige Konstruktion haben, in der Sie nach dem Aufruf des Konstruktors eine init() Methode aufrufen. Es gibt jedoch keine Möglichkeit, die am meisten abgeleitete Version einer virtuellen Funktion vom Konstruktor sicher aufzurufen.

Hoffe, das hilft!

Verwandte Themen