c++ - 如何将函数传递给 C++ 中的类?
问题描述
所以我一直在研究一个通过 USB 发送 MIDI 数据的 Arduino 程序,我似乎无法弄清楚如何将处理发送 MIDI 数据的函数传递给我的主类。它在某些时候有效,但由于某种原因,它没有,我觉得我已经尝试了各种组合。
这是我的主文件,简化为仅通过串行输出 MIDI 数据:
#include "XiaoPiezoDrum.h"
void sendNoteOn(int note, int velocity, int chan) {
Serial.printf("WORKS! %d %d %d\n", note, velocity, chan);
};
XiaoPiezoDrum drum(9, 2, 3, 4);
void setup() {
drum.setNoteComFunctions(sendNoteOn);
}
这是setNoteComFunctions方法的样子:
void XiaoPiezoDrum::setNoteComFunctions(const std::function<void(int, int, int)>& onFunc) {
sendNote = [onFunc](auto && PH1, auto && PH2, auto && PH3) { onFunc(PH1, PH2, PH3); };
}
这是主类定义的相关部分:
class XiaoPiezoDrum {
public:
XiaoPiezoDrum();
XiaoPiezoDrum(int piezoPin, int rPin, int gPin, int bPin);
void setNoteComFunctions(const function<void(int, int, int)>& onFunc);
void RunCycle();
private:
std::function<void(int, int, int)> sendNote;
}
所以一切都运行得很好,直到我从RunCycle 中调用 sendNote ,这只是在每个循环中调用,然后串行通信突然停止。我究竟做错了什么?我也尝试使用 bind 而不是 lambda,并且发生了同样的事情。当我只是将主文件中sendNoteOn中的相同打印语句复制到setNoteComFunctions中的 lambda 中时,它打印得很好,所以我知道问题在于从主文件链接函数。
我尝试过的事情:
- 将setNoteComFunctions中的函数作为参考而不是作为参考传递
- 使用 bind 而不是 lambda
- 更改sendNoteOn的正文
- 使 lambda 参数引用
- 使 lambda 参数不是引用
- 在 lambda 中返回onFunc
几个小时以来,我一直在用头撞键盘。如果有人知道我做错了什么,我希望得到一个解释!
编辑 这是RunCycle的完整代码。其中许多变量是我在提供的类定义中遗漏的实例变量,但我知道问题出在sendNote的调用上,因为如果我将其注释掉,事情会继续正常运行。我也尝试用固定整数替换速度变量,同样的事情发生了。
void XiaoPiezoDrum::RunCycle() {
double val = sensor.read();
val = (val > 0) ? val : 0;
Serial.println(val);
unsigned long timeElapsed;
int velocity;
MaxVal = (val > MaxVal) ? val : MaxVal;
trigger = val > THRESHOLD && !triggering;
if (val > THRESHOLD && !triggering) trigger = true;
if (trigger) {
triggerTime = millis();
trigger = false;
triggering = true;
triggerBuffer.clear();
}
if (triggering) {
timeElapsed = millis() - triggerTime;
if (timeElapsed < SAMPLE_TIME) {
loopCounter++;
triggerBuffer.addValue(val);
Serial.println(val);
}
else {
velocity = map(round(triggerBuffer.getMax()), 0, 300, THRESHOLD, 127);
Serial.printf("Velocity: %d\n", velocity);
if (comFunctionsSet) sendNote(40, velocity, 1);
noteEndTime = millis();
triggerTime = 0;
triggerBuffer.clear();
triggering = false;
resting = true;
}
}
}
解决方案
jignatius的回答做到了!我早该知道我能做到的!!谢谢!
我只需要更换
void XiaoPiezoDrum::setNoteComFunctions(const std::function<void(int, int, int)>& onFunc) {
sendNote = [onFunc](auto && PH1, auto && PH2, auto && PH3) { onFunc(PH1, PH2, PH3); };
}
和:
void XiaoPiezoDrum::setNoteComFunctions(const std::function<void(int, int, int)>& onFunc) {
sendNote = onFunc;
}
很高兴解决了这个问题!谢谢!
推荐阅读
- python - 通过使用 BeautifulSoup 递归抓取网站来收集音乐艺术家
- sql-server - SQL join 避免笛卡尔积
- angular - 在角度材料卡中显示不同的内容
- mysql - 如何使用位置中心/所有美国邮政编码创建一对多映射的 MySQL 数据库?
- javascript - AdWords 范围:使用 OAuth 流程进行身份验证后缺少 gapi.client.adwords。找不到要传递给 gapi.client.request() 的路径变量
- google-cloud-datastore - 谷歌数据存储交易异常
- python - Pandas 根据字符串列值有条件地设置值
- java - sharedPrefrences 上下文空指针,跨活动
- javascript - 将值发送到另一个文件 JS
- c# - 如何使用 NAudio 从 WASAPI 设备获取样本中的实际缓冲区大小?