2012-06-19 36 views
5

Mam klasy bazowej o nazwie Panel, gdzie przechowywane są niektóre informacje o oknie, a następnie mam podklas dla wszystkich formantów: Button, Label itp. W klasie bazowej mam metodę virtual void ApplySchemeSettings(Scheme* scheme) { } , która jest wywoływana w ramach konstruktora Panel(Panel* parent). Ale zamiast podklasy jest wywoływana ApplySchemeSettings z klasy bazowej (Panel).Metoda wirtualna nie jest wywoływana

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"); 
    } 
} 

Nie mogę zadeklarować ApplySchemeSettings jako abstrakcyjny, ponieważ podklasy jest przez użytkownika.

+1

'this-> ApplySchemeSettings (scheme());' typem tego "wskaźnika" w punkcie wywołania jest 'Panel * const', więc wywołuje' Panel :: ApplySchemeSettings'. Morał fabuły nigdy nie jest nazywany funkcją wirtualną od konstruktora klasy bazowej. –

+0

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

+0

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

Odpowiedz

8

Wewnątrz konstruktora funkcje wirtualne nie zachowują się tak, jak można się spodziewać. W szczególności każde wywołanie funkcji wirtualnej wewnątrz konstruktora zawsze rozwiąże wywołanie funkcji wersji zadeklarowanej wewnątrz bieżącej klasy. Powodem tego jest to, że podczas konstruowania obiektu, klasa jest konstruowana najpierw przez skonstruowanie najbardziej skonstruowanej klasy bazowej, następnie jej klasy potomnej, następnie jej klasy potomnej, itd. W konsekwencji, podczas konstruowania obiektu, klasy pochodne nie są inicjowane aż do bazy konstruktorzy klasy kończą pracę. Gdybyś mógł wywołać funkcję wirtualną i ją rozwiązać do najbardziej wyprowadzonej wersji wewnątrz konstruktora klasy podstawowej, wywoływałbyś metodę na klasie, która nie została jeszcze w ogóle zainicjalizowana - nawet domyślna Konstruktory dla członków danych zostałyby jeszcze wywołane.

Będziesz musiał znaleźć inne podejście do rozwiązania tego problemu. Możesz na przykład mieć dwuetapową konstrukcję, w której wywołujesz metodę init() po wywołaniu konstruktora. Jednak nie ma sposobu, aby bezpiecznie wywołać najbardziej pochodną wersję funkcji wirtualnej z konstruktora.

Mam nadzieję, że to pomoże!

Powiązane problemy