如何让编译器自动复用多MIDI设备代码,避免手动重复编写?
解决Teensy多MIDI源的代码重复问题
问题背景
我正在开发一款基于Teensy 4.1、由MIDI消息控制的合成器,需要同时支持多个MIDI源:
- 最初适配USB Device MIDI:只需在
setup()中设置8个回调函数,loop()里调用usbMIDI.read()即可。 - 后续适配USB Host MIDI时出现代码重复:回调设置和
loop()中的read()调用都要重复编写。我把多个USB Host MIDI源对象的指针存入数组,在setup()和loop()中遍历操作,但仍需为USB Device保留重复代码。 - 现在要添加Teensy硬件串口实现的5-pin DIN MIDI端口,这会让相同调用代码出现三次,急需更优方案。
当前重复代码示例
void setup() { // USB Device usbMIDI.setHandleNoteOff(myNoteOff); usbMIDI.setHandleNoteOn(myNoteOn); usbMIDI.setHandlePitchChange(myPitchChange); // ... 其他6个回调设置 // USB Host for(uint8_t i = 0; i < CNT_MIDI; i++) { midiDevices[i]->setHandleNoteOff(myNoteOff); midiDevices[i]->setHandleNoteOn(myNoteOn); midiDevices[i]->setHandlePitchChange(myPitchChange); // ... 其他6个回调设置 } } ... void loop() { usbMIDI.read(); for(uint8_t i = 0; i < CNT_MIDI; i++) midiDevices[i]->read(); // ... 其他逻辑 }
核心痛点
USB Device类(usb_midi_class)和USB Host类(MIDIDeviceBase)的read()、setHandle...(函数指针)接口完全一致,但没有共同基类,无法把USB Device对象加入USB Host指针数组。我的目标是无需手动编写三次相同调用,由编译器自动对三种类型对象调用同名成员函数,且设备是编译时确定的,运行时不会增减。
尝试过的方案(存在不足)
我考虑过用公共基类加模板包装类,但仍需重复编写代码,还要手动写出8个带函数指针的签名:
class Wrapper { public: virtual bool read(uint8_t channel) = 0; virtual ~Wrapper() = 0; // ... 手动声明8个setHandle...纯虚函数 }; template <class T> class TemplateWrapper : public Wrapper { private: T* wrapped; public: TemplateWrapper(T* w) : wrapped(w) {} bool read(uint8_t channel) { return wrapped->read(channel); } // ... 手动实现8个setHandle...成员函数 };
需求
有没有更优的方案,避免上述重复代码?
内容的提问来源于stack exchange,提问作者Christopher Dickey
相关产品推荐
相关产品推荐

