C引用在函数范围内创建的实例
上下文
问题的背景是我正在编写一个与Arduino一起使用的小型库,以便充当游戏控制器.我遇到的问题与C有关,而不是Arduino的具体问题. 我已经在下面包含了库的头文件和源代码,然后是Arduino代码.我尽可能地截断了它. 问题 简而言之,只有我定义的最后一个开关/动作实际上得到了正确的句柄. 这些操作在Arduino设置功能中定义.例如: controller.addSwitchContinuous(10,0); // Pin 10; btn index 0 表示引脚10映射到按钮0.当引脚10关闭时,这被视为按下按钮.这适用于单个动作,但是当我开始添加更多时,只有最后一个动作才有效.因此,在以下示例中,仅识别引脚9: controller.addSwitchContinuous(10,0); // <-- Doesn't work controller.addSwitchContinuous(9,1); // <-- Works 这适用于任意数量的操作: controller.addSwitchContinuous(10,1); // <-- Doesn't work controller.addSwitchContinuous(8,2); // <-- Doesn't work controller.addSwitchContinuous(7,3); // <-- Works 可能的原因 我是C的新手,所以我怀疑我做错了指针.更具体地说,Joystick_实例如何传递似乎有些问题. 我一直在摆弄构造函数并尝试使用引用而不是指针,但我无法让它正常工作. 我可以确认JFSF ::循环中的迭代会迭代所有操作,如果我修改它: void JFSF::loop() { for (int n = 0; n < _nextActionIndex; n++) { if (_actions[n]) { _actions[n]->loop(); _joystick->setButton(n,PRESSED); // Debug: Set button pressed,regardless of switch. } } if (_doSendState) { _joystick->sendState(); } } 按钮0到n按预期按下.可能没有正确地调用loop(),但是在这种情况下,我希望N = 1的情况也会失败.此外,最后一个动作总是成功的事实表明迭代是可以的. 完整代码 // JFSF.h #ifndef JFSF_h #define JFSF_h // ... include for Arduino.h and Joystick.h; bunch of defines namespace JFSF_PRIV { class AbstractAction { public: virtual void loop(); }; /* A Switch that essentially acts as a push button. */ class SwitchContinuousAction : public AbstractAction { public: SwitchContinuousAction(Joystick_ *joystick,int pin,int btnIndex); void loop(); private: Joystick_ *_joystick; int _pin; int _btnIndex; }; } // namespace JFSF_PRIV class JFSF { public: JFSF(Joystick_ *joystick,bool doSendState); // doSendState should be true if Joystick_ does not auto send state. void loop(); void addSwitchContinuous(int inputPin,int btnIndex); private: Joystick_ *_joystick; JFSF_PRIV::AbstractAction *_actions[MAX_ACTIONS]; int _nextActionIndex; bool _doSendState; }; #endif 源文件(修剪): // JFSF.cpp #include "Arduino.h" #include "Joystick.h" #include "JFSF.h" #define PRESSED 1 #define RELEASED 0 // Private classes namespace JFSF_PRIV { SwitchContinuousAction::SwitchContinuousAction(Joystick_ *joystick,int btnIndex) { _joystick = joystick; _pin = pin; _btnIndex = btnIndex; pinMode(_pin,INPUT_PULLUP); } void SwitchContinuousAction::loop() { int _state = digitalRead(_pin) == LOW ? PRESSED : RELEASED; _joystick->setButton(_btnIndex,_state); } } // namespace JFSF_PRIV JFSF::JFSF(Joystick_ *joystick,bool doSendState) { _joystick = joystick; _nextActionIndex = 0; _doSendState = doSendState; } void JFSF::addSwitchContinuous(int inputPin,int btnIndex) { JFSF_PRIV::SwitchContinuousAction newBtnAction(_joystick,inputPin,btnIndex); _actions[_nextActionIndex++] = &newBtnAction; } void JFSF::loop() { for (int n = 0; n < _nextActionIndex; n++) { if (_actions[n]) { _actions[n]->loop(); } } if (_doSendState) { _joystick->sendState(); } } 为了完整起见,这是Arduino的代码,但它几乎只是声明: #include <JFSF.h> // ... A bunch of const declarations used below. These are pretty self explanatory. // See: https://github.com/MHeironimus/ArduinoJoystickLibrary#joystick-library-api Joystick_ joystick(HID_REPORT_ID,JOYSTICK_TYPE_JOYSTICK,// _JOYSTICK,_GAMEPAD or _MULTI_AXIS BTN_COUNT,HAT_SWITCH_COUNT,INCLUDE_X_AXIS,INCLUDE_Y_AXIS,INCLUDE_Z_AXIS,INCLUDE_RX_AXIS,INCLUDE_RY_AXIS,INCLUDE_RZ_AXIS,INCLUDE_RUDDER,INCLUDE_THROTTLE,INCLUDE_ACCELERATOR,INCLUDE_BRAKE,INCLUDE_STEERING); JFSF controller(&joystick,!DO_AUTO_SEND_STATE); void setup() { joystick.begin(DO_AUTO_SEND_STATE); controller.addSwitchContinuous(10,0); // <-- Doesn't work controller.addSwitchContinuous(9,1); // <-- Works } void loop() { controller.loop(); } 参考 可以在此处找到ArduinoJoystickLibrary(Joystick_的来源):https://github.com/MHeironimus/ArduinoJoystickLibrary#joystick-library-api 解决方法
我真的不明白你的代码.请阅读
How to create a Minimal,Complete and Verifiable example.无论如何,以下肯定是错误的,可能是您的问题的原因:
void JFSF::addSwitchContinuous(int inputPin,btnIndex); _actions[_nextActionIndex++] = &newBtnAction; } 为了清楚起见,让我们重写一下: void foo(){ T bar; container[index] = &bar; } 这里发生的事情是当bar超出范围时会被销毁,因此你放入容器的指针指向垃圾.大概在你的代码中的某个地方,你正在取消引用那些指针,这是未定义的行为(也就是任何事情都可能发生). 长话短说:过度使用指针是c初学者的常见模式.很可能你应该把容器变成对象的容器而不是指针,并利用自动内存管理而不是试图对抗它. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |