Как производный класс может наследовать статическую функцию от базового класса? - PullRequest
24 голосов
/ 05 февраля 2009
struct TimerEvent
{
   event Event;
   timeval TimeOut;
   static void HandleTimer(int Fd, short Event, void *Arg);
};

HandleTimer должен быть статическим, так как я передаю его в библиотеку C (libevent).

Я хочу наследовать от этого класса. Как это можно сделать?

Спасибо.

Ответы [ 3 ]

40 голосов
/ 05 февраля 2009

Вы можете легко наследовать от этого класса:

class Derived: public TimerEvent {
    ...
};

Однако вы не можете переопределить HandleTimer в своем подклассе и ожидать, что это сработает:

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

Это потому, что статические методы не имеют записи в виртуальной таблице и поэтому не могут быть виртуальными. Однако вы можете использовать "void * Arg", чтобы передать указатель на ваш экземпляр ... что-то вроде:

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

Таким образом, HandleTimer все еще может использоваться из функций C, просто убедитесь, что «настоящий» объект всегда передается как «void * Arg».

16 голосов
/ 12 июня 2015

В некоторой степени паттерн черт позволяет вам наследовать и переопределять статические методы.

Первый старт с базового класса:

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

Затем выведите его и переопределите несколько методов:

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

А теперь вызовите методы через класс черт:

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

Класс traits позволяет вам повторно использовать статический метод base::shout, одновременно "переопределяя" base::talk с помощью derived::talk. Тем не менее, есть несколько различий с фактическим наследованием:

  • Функция для вызова разрешается во время компиляции
  • Дочерний метод не обязательно должен иметь ту же подпись, что и родительский

Он также работает со статическими полями и typedefs, лучший пример это std :: iterator_traits .

0 голосов
/ 06 февраля 2009

У вас есть небольшой конфликт в вашем вопросе. Когда вы передаете &TimerEvent::TimerHandler в библиотеку C, вы делаете именно это. Вы также могли бы сдать &DerivedTimerEvent::TimerHandler, если хотите. Но вы не можете передать &TimerEvent::TimerHandler и ожидать, что C библиотека (!) Покажет, что вы действительно имели в виду &DerivedTimerEvent::TimerHandler.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...