組み込みデバイス (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
ます。どうすればそれを達成できますか?
全体として、これは理にかなっていますか?継承を使用せずにコールバックを注入するより良い方法はありますか?