web-dev-qa-db-ja.com

派生クラスはどのようにして基本クラスから静的関数を継承できますか?

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

HandleTimerは、Cライブラリ(libevent)に渡すため、静的である必要があります。

このクラスを継承したい。これはどのように行うことができますか?

ありがとう。

24
jackhab

そのクラスから簡単に継承できます。

class Derived: public TimerEvent {
    ...
};

ただし、サブクラスのHandleTimerをオーバーライドしてこれが機能することを期待することはできません。

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

これは、静的メソッドはvtableにエントリを持たないため、仮想にすることができないためです。ただし、「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
    }
};

このようにして、C関数からHandleTimerを引き続き使用できます。必ず、「実際の」オブジェクトを常に「void * Arg」として渡すようにしてください。

40
Joao da Silva

ある程度の特性パターンにより、静的メソッドを継承および再定義できます。

まず、基本クラスから始めます。

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デモ

トレイトクラスを使用すると、base::shoutbase::talkで「オーバーライド」しながら、静的メソッドderived::talkを再利用できます。それでも、実際の継承にはいくつかの違いがあります。

  • 呼び出す関数はコンパイル時に解決されます
  • 子メソッドは親メソッドと同じシグネチャを持つ必要はありません

静的フィールドとtypedefでも機能します。最も良い例は std :: iterator_traits です。

21
xavlours

あなたの質問には、少し矛盾があります。 &TimerEvent::TimerHandlerをCライブラリに渡すと、まさにそのとおりになります。必要に応じて、&DerivedTimerEvent::TimerHandlerを渡すこともできます。ただし、&TimerEvent::TimerHandlerを渡してCライブラリ(!)で実際に&DerivedTimerEvent::TimerHandlerを意味していることを理解することはできません。

0
MSalters