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 !!"
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 .