2

組み込みデバイス (ESP32) 用に C コードベースを C++ に変換しています。現在のコードで繰り返されていることの 1 つは、C モジュールへの「コールバック」を宣言し、それらを「ユーザー」モジュールに実装する方法です。

たとえば、Button モジュールの現在の API は次のとおりです。

void btn_init(uint32_t gpio);

// callbacks
extern bool btn_on_change_isr(bool is_pressed, uint32_t timer_duration_s);
extern bool btn_on_timer_isr(uint32_t duration_s);

関数がデフォルトで ed であることを知っているexternので、これは単にモジュールがそれらを実装する責任を負っていないという印です。このメソッドの主な利点は、未実装のコールバックがコンパイル時にリンカーによってキャッチされることです。

C++ への移行中、コールバック実装の存在をコンパイル時にチェックしたい (動的ディスパッチは必要ありません) と同時に、複数のオブジェクトを作成できるようにするため、クラスが必要です。

私は CRTP とポリシーベースの設計は初めてですが、これらのいずれかを使用する必要があると思います。それともテンプレートファンクターですか?これら2つの違いは何ですか?

私の現在の考えは次のとおりです。

template <typename Impl>
class Button
{
  public:
    Button(uint32_t gpio, Impl impl_ = Impl())
        : impl(impl_)
    {
        (void)gpio;
    }
    bool on_change_isr(bool is_pressed, uint32_t timer_duration_s)
    {
        return impl.on_change_isr(is_pressed, timer_duration_s);
    }
    bool on_timer_isr(uint32_t duration_s)
    {
        return impl.on_timer_isr(duration_s);
    }

  private:
    Impl impl;
};

実装コードは次のとおりです。

class MyButton
{
public:
    bool on_change_isr(bool is_pressed, uint32_t timer_duration_s)
    {
       // implementation 
    }
    bool on_timer_isr(uint32_t duration_s)
    {
       // implementation 
    }
};

ここで私を悩ませている主な点の 1 つは、実装をcppヘッダーではなくファイルに保持したいということです。クラスについてはButton、コンストラクターをファイルに実装したいと思いcppます。どうすればそれを達成できますか?

全体として、これは理にかなっていますか?継承を使用せずにコールバックを注入するより良い方法はありますか?

4

0 に答える 0