当前位置 : 主页 > 编程语言 > c++ >

C引用在函数范围内创建的实例

来源:互联网 收集:自由互联 发布时间:2021-06-23
上下文 问题的背景是我正在编写一个与Arduino一起使用的小型库,以便充当游戏控制器.我遇到的问题与C有关,而不是Arduino的具体问题. 我已经在下面包含了库的头文件和源代码,然后是Ar
上下文

问题的背景是我正在编写一个与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, 0);  // <-- Doesn't work
controller.addSwitchContinuous(9, 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 pin, 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, int btnIndex)
{
    JFSF_PRIV::SwitchContinuousAction newBtnAction(_joystick, inputPin, btnIndex);
    _actions[_nextActionIndex++] = &newBtnAction;
}

为了清楚起见,让我们重写一下:

void foo(){
    T bar;
    container[index] = &bar;
}

这里发生的事情是当bar超出范围时会被销毁,因此你放入容器的指针指向垃圾.大概在你的代码中的某个地方,你正在取消引用那些指针,这是未定义的行为(也就是任何事情都可能发生).

长话短说:过度使用指针是c初学者的常见模式.很可能你应该把容器变成对象的容器而不是指针,并利用自动内存管理而不是试图对抗它.

网友评论