2012-03-15 22 views
13

Tengo algunos eventos como esteFuerza llamar a la clase base función virtual

class Granpa // this would not be changed, as its in a dll and not written by me 
{ 
public: 

    virtual void onLoad(){} 

} 

class Father :public Granpa // my modification on Granpa 
{ 
public: 

    virtual void onLoad() 
    { 
     // do important stuff 
    } 

} 

class Child :public Father// client will derive Father 
{ 

    virtual void onLoad() 
    { 
     // Father::onLoad(); // i'm trying do this without client explicitly writing the call 

     // clients code 
    } 
} 

¿Hay una manera de forzar onLoad llamando sin escribir Padre :: onLoad()?

soluciones hacker son bienvenidos :)

+4

No entiendo por qué esto es un problema. Desea hacer algo explícitamente, por lo que debe decirlo explícitamente en el código ... –

+2

¿Es un poco vago no agregar una línea de código para hacer algo que desea que ocurra de forma explícita? –

+0

Dado que el mismo problema no se resuelve en, por ejemplo, los controladores MFC (siempre debe llamar explícitamente a CDialog :: OnInitDialog() desde su CMyDialog :: OnInitDialog()), creo que puede requerir que el usuario haga eso. – Mikhail

Respuesta

24

Si he entendido bien, usted lo desea de manera que cada vez que la función se llama a overriden, la implementación de la clase base debe siempre llamará en primer lugar. En ese caso, puede investigar el template pattern. Algo como:

class Base 
{ 
public: 
    void foo() { 
     baseStuff(); 
     derivedStuff(); 
    } 

protected: 
    virtual void derivedStuff() = 0; 
private: 
    void baseStuff() { ... } 
}; 

class Derived : public Base { 
protected: 
    virtual void derivedStuff() { 
     // This will always get called after baseStuff() 
     ... 
    } 
}; 
+2

También conocido como interfaz no virtual (aunque siempre lo he conocido como patrón de método de plantilla). –

+0

derivedStuff también puede ser privado en ambas clases. – Dan

+2

Una buena explicación también se puede encontrar aquí http://www.gotw.ca/publications/mill18.htm – pmr

4

Como se sugirió anteriormente, pero se aplica a su caso.

class Father :public Granpa // my modification on Granpa 
{ 

public: 

    virtual void onLoad() 
    { 
     // do important stuff 
     onLoadHandler(); 
    } 
    virtual void onLoadHandler()=0; 
} 

class Child :public Father// client will derive Father 
{ 

    virtual void onLoadHandler() 
    { 

     // clients code 
    } 
} 

Sin embargo, nada puede evitar Niño para anular onLoad ya que C++ no tiene ninguna palabra clave final y Granpa onLoad es en sí virtual.

+4

Afortunadamente, C++ 11 tiene una palabra clave final. – juanchopanza

2

Bueno, no hay una forma ampliamente conocida y reconocida de hacer esto. Si hubiera existido, las bibliotecas de GUI que usan eventos y señales probablemente lo habrían implementado. Sin embargo, hay otras soluciones a su problema.

Puede implementar una conexión de señal de evento, usando boost.Signals, sigslot o algo por su cuenta. Como GTK + hace:

g_signal_connect(my_wdg, "expose-event", G_CALLBACK(my_func), NULL); 

gboolean my_func(...) 
{ 
    // do stuff 
    return FALSE; /* this tells the event handler to also call the base class's slot */ 
} 

En una forma menos C-céntrico, esto podría ser implementado a lo largo de estas líneas:

/* In Granpa */ 
/* typedef a functor as 'DerivedEventHandler' or use a boost::function */ 
std::vector<DerivedEventHandler> handlers; 

void connect(DerivedEventHandler event) { handlers.push_back(event); } 

/* in loop */ 
while (! iter = handlers.end()) /* call event */ 

/* In constructor of Father */ 
this->connect(this->OnLoad); 

/* In constructor of Child */ 
this->connect(this->OnLoad); 

/* and so on... in all derived classes */ 
-1

Si el objeto en cuestión es pequeño y barato para copiar, simplemente llame a la base class 'copy constructor, es decir, BaseClass (* derived_class_object) .method()

+0

Probablemente no era lo que OP quería, ya que le preguntó cómo hacerlo sin escribir explícitamente la llamada a la función baseClass, que también tendría que ver con este enfoque. – Haatschii

Cuestiones relacionadas