4

私は、関数ポインターとサブクラス化されたオブジェクトのどちらかを選択する立場にあります。明確にするために、何らかのアクション (タイマーなど) をオブジェクトに通知する必要があるとします。次の 2 つの選択肢を参照してください (デモ用の非常に基本的なコードです)。

バージョン 1

typedef void TimerCallback(void *args);
class Timer{
public:
  Timer();
  ~Timer();
  void schedule(TimerCallback *callback, void *args, long timeout)=0;
  void cancel();
};

バージョン 2

class TimerTask{
  public:
    TimerTask();
    virtual ~TimerTask();
    void timedout()=0;
};
class Timer{
  public:
    Timer();
    virtual ~Timer();
    void schedule(TimerTask *callback, long timeout)=0;
    void cancel();
};

どれが標準的な C++ の方法で、どれが効率的ですか? この点に関して他に提案があれば教えてください。

この点について不明な点がある場合はお知らせください。

ありがとう

4

5 に答える 5

14

と. std::function_ 次に、継承されたクラス、スタンドアロン関数、メンバー関数、またはラムダstd::bindを使用するかどうかは問題ではありません。


ところで、誰かが興味を持っている場合は、別の質問への回答として、少し前に簡単なタイマー イベント処理を作成しました。std::functionたとえば、https://stackoverflow.com/a/11866539/440558の使用を紹介していstd::bindます。

于 2013-02-25T12:53:55.223 に答える
4

boost(or std since C++11)::functionコールバックを保持しboost::bindてその引数をバインドするために使用するか、を使用する方が良いと思いますboost::signal。これは、非常に小さなペナルティを犠牲にして、より一般的で冗長なソリューションになります。

http://www.boost.org/doc/libs/1_53_0/doc/html/signals2.html

于 2013-02-25T12:53:06.857 に答える
2

オブジェクト指向プログラミングを使用しており、オブジェクト指向プログラミング パラダイムに従う必要があります。

私の意見では、関数ポインターではなくオブジェクトを使用する方が、クリーンで一般的に優れた方法です。

また、ビジター パターンを使用して、コードをより適切かつ柔軟にすることもできます。

パブリッシャー/サブスクライバー パターンを検討することもできます。

于 2013-02-25T12:52:26.053 に答える
1

関数ポインターは、クロージャーの使用を効果的に防ぎます-メソッドをイベントハンドラーに割り当てます(これは完全に真実ではありませんが、このソリューションがあまり役に立たないような方法で制限されます)。

私はオブジェクト指向のアプローチに投票します。C++11 を使用している場合は、コードを大幅に簡素化できます。

#include <cstdio>
#include <functional>

class Emitter
{
private:
    std::function<void(int)> eventHandler;

public:
    void SetEventHandler(std::function<void(int)> newEventHandler)
    {
        eventHandler = newEventHandler;
    }

    void EmitEvent()
    {
        eventHandler(42); // + error-checking
    }
};

class Handler
{
private:
    void HandleEvent(int i)
    {
        printf("Event handled with i == %d\n", i);
    }

public:
    void AttachEmitter(Emitter & e)
    {
        e.SetEventHandler([this](int i) { HandleEvent(i); });
    }
};

int main(int argc, char * argv[])
{
    Emitter e;
    Handler h;

    h.AttachEmitter(e);
    e.EmitEvent();
}
于 2013-02-25T12:57:26.877 に答える
0

どちらも機能します。あなたの最初のものは「Cスタイル」で、どこかに静的関数が必要です。2 番目のバージョンは「C++ スタイル」で、TimerTask のインスタンスを使用できます。

一般に、バージョン 2 を使用する必要があります。これは、静的関数が不要になるためです。

于 2013-02-25T12:54:42.127 に答える