我正在为嵌入式设备(ESP32)将 C 代码库转换为 C++。在当前代码中重复的一件事是向 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);
知道函数是extern
默认编辑的,这只是一个标志,表明模块不是负责实现它们的人。此方法的主要优点是链接器在编译时捕获未实现的回调。
在过渡到 C++ 时,我想保持编译时检查回调实现的存在(我不需要动态调度),但也允许创建多个对象,所以我需要类。
虽然我是 CRTP 和基于策略的设计的新手,但我想我应该选择其中之一。或者可能是模板函子?这两者有什么区别?
我目前的想法如下:
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
}
};
让我感到困扰的一件主要事情是我仍然希望将实现保留在cpp
文件中而不是标题中。对于这个Button
类,我想在一个cpp
文件中实现构造函数。我怎样才能做到这一点?
总的来说,这有意义吗?有没有更好的方法来注入回调而不使用继承?