2009-02-05 25 views
20
struct TimerEvent 
{ 
    event Event; 
    timeval TimeOut; 
    static void HandleTimer(int Fd, short Event, void *Arg); 
}; 

HandleTimer debe ser estático ya que lo paso a la biblioteca C (libevent).¿Cómo puede la clase derivada heredar una función estática de la clase base?

Quiero heredar de esta clase. ¿Cómo puede hacerse esto?

Gracias.

+0

Simplemente herede y debería funcionar. ¿Tienes algún problema en particular con esto? – jpalecek

+0

Estoy de acuerdo con el comentario anterior, no entiendo la pregunta. –

+0

Tercero el comentario anterior. :) –

Respuesta

33

Puede heredar fácilmente de esa clase:

class Derived: public TimerEvent { 
    ... 
}; 

Sin embargo, no se puede anular HandleTimer en la subclase y esperar que esto funcione:

TimerEvent *e = new Derived(); 
e->HandleTimer(); 

Esto se debe a métodos estáticos Don' t tiene una entrada en el vtable, y por lo tanto no puede ser virtual. Sin embargo, puede utilizar el "void * Arg" para pasar un puntero a la instancia ... algo así como:

struct TimerEvent { 
    virtual void handle(int fd, short event) = 0; 

    static void HandleTimer(int fd, short event, void *arg) { 
     ((TimerEvent *) arg)->handle(fd, event); 
    } 
}; 

class Derived: public TimerEvent { 
    virtual void handle(int fd, short event) { 
     // whatever 
    } 
}; 

De esta manera, HandleTimer todavía se puede utilizar desde las funciones de C, sólo asegúrese de pasar siempre el " verdadero "objeto como el 'vacío' Arg".

+0

no es necesario usar estático como este, prefiero usar: derivado t; t.handle (...); – raidsan

0

Aquí tienes un poco de conflicto en tu pregunta. Cuando pasa &TimerEvent::TimerHandler a una biblioteca C, hace exactamente eso. También podría haber pasado &DerivedTimerEvent::TimerHandler, si lo desea. Pero no puede pasar &TimerEvent::TimerHandler y esperar que la biblioteca C (!) Descubra que en realidad quiere decir &DerivedTimerEvent::TimerHandler.

+1

Dado que es 'estático', espero que el compilador resuelva eso mucho antes de que el flujo llegue a la biblioteca C. –

8

Hasta cierto punto, el patrón de rasgos le permite heredar y redefinir los métodos estáticos.

primer comienzo con una clase base:

struct base { 
    static void talk() { std::cout << "hello" << std::endl; } 
    static void shout() { std::cout << "HELLO !!" << std::endl; } 
}; 

Entonces derivarla y redefinir algunos métodos:

struct derived: public base { 
    static void talk() { std::cout << "goodbye" << std::endl; } 
}; 

Y ahora llamar a los métodos a través de una clase de rasgos:

template < class T > 
struct talker_traits { 
    static void talk() { T::talk(); } 
    static void shout() { T::shout(); } 
}; 

talker_traits<base>::talk()  // prints "hello" 
talker_traits<base>::shout() // prints "HELLO !!" 

talker_traits<derived>::talk() // prints "goodbye" 
talker_traits<derived>::shout() // prints "HELLO !!" 

ideone demo

La clase de rasgos le permite reutilizar el método estático base::shout mientras "anula" base::talk con derived::talk. Sin embargo, hay varias diferencias con la herencia real:

  • la función a llamar se resuelve en tiempo de compilación
  • El método niño no necesita tener la misma firma que el padre de un

Funciona con campos estáticos y typedefs también, el mejor ejemplo es std::iterator_traits.

Cuestiones relacionadas