poo modo hijo herencia ejemplos derivadas derivada clases clase c++ inheritance static

c++ - modo - ¿Cómo puede la clase derivada heredar una función estática de la clase base?



herencia poo (3)

struct TimerEvent { event Event; timeval TimeOut; static void HandleTimer(int Fd, short Event, void *Arg); };

HandleTimer necesita ser estático ya que lo paso a la biblioteca C (libevent).

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

Gracias.


Usted puede heredar fácilmente de esa clase:

class Derived: public TimerEvent { ... };

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

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

Esto se debe a que los métodos estáticos no tienen una entrada en el vtable, y por lo tanto no pueden ser virtuales. Sin embargo, puede usar "void * Arg" para pasar un puntero a su 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 forma, HandleTimer se puede usar desde las funciones C, solo asegúrese de pasar siempre el objeto "real" como "void * Arg".


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 se refería a &DerivedTimerEvent::TimerHandler .


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

Primero comienza con una clase base:

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

A continuación, derivarlo y redefinir algunos métodos:

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

Y ahora llama 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 !!"

demo de ideone

La clase de rasgos le permite reutilizar el método estático base::shout mientras "reemplaza" a base::talk con derived::talk . Aún así, hay varias diferencias con la herencia real:

  • La función para llamar se resuelve en tiempo de compilación
  • El método secundario no necesita tener la misma firma que el padre

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