2012-06-19 26 views
5

Tengo una clase base llamada Panel, donde se almacena cierta información sobre una ventana, luego, tengo subclases para todos los controles: Botón, Etiqueta, etc. En la clase base, tengo el método virtual void ApplySchemeSettings(Scheme* scheme) { } , que se llama dentro del constructor Panel(Panel* parent). Pero en lugar de la subclase, se llama al ApplySchemeSettings de la clase base (Panel).Método virtual que no se llama

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

no puedo declarar como ApplySchemeSettings abstracta porque las subclases se hace por el usuario.

+1

'this-> ApplySchemeSettings (scheme());' el tipo de puntero 'this' en el punto de llamada es' Panel * const', por lo que invoca 'Panel :: ApplySchemeSettings'. La moraleja de la historia nunca se llama función virtual desde el constructor de la clase base. –

+0

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

+0

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

Respuesta

8

Dentro de un constructor, las funciones virtuales no se comportan como cabría esperar. En particular, cualquier llamada a una función virtual dentro de un constructor siempre resolverá la llamada a la versión de la función declarada dentro de la clase actual. La razón de esto es que durante la construcción del objeto, una clase se construye teniendo primero la clase más básica construida, luego su clase secundaria, luego su clase secundaria, etc. En consecuencia, durante la construcción del objeto, las clases derivadas no se inicializan hasta la base constructores de clase terminan funcionando. Si fuera capaz de invocar una función virtual y resolverla en la versión más derivada dentro de un constructor de clase base, estaría invocando un método en una clase que aún no se había inicializado, ni siquiera el valor predeterminado los constructores para los miembros de datos habrían sido llamados todavía.

Tendrá que buscar otro enfoque para resolver este problema. Es posible que, por ejemplo, tenga una construcción en dos pasos en la que llame a algún método init() después de llamar al constructor. Sin embargo, no hay forma de llamar de forma segura a la versión más derivada de una función virtual desde el constructor.

Espero que esto ayude!

Cuestiones relacionadas