gpt4 book ai didi

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

转载 作者:太空狗 更新时间:2023-10-29 20:20:06 26 4
gpt4 key购买 nike

上下文

问题的背景是我目前正在编写一个与 Arduino 一起使用的小型库,以充当游戏 Controller 。然而,我遇到的问题更多地与 C++ 有关,而不是 Arduino 特定的问题。

我在下面包含了库的标题和源代码,然后是 Arduino 代码。我已尽可能截断它。

问题

简而言之,实际上只有我定义的最后一个开关/操作得到正确处理。

这些操作在 Arduino 设置函数中定义。例如:

controller.addSwitchContinuous(10, 0);  // Pin 10; btn index 0

表示引脚 10 映射到按钮 0。当引脚 10 关闭时,这被视为按钮被按下。这适用于单个 Action ,但当我开始添加更多时,只有最后一个 Action 真正起作用。所以在下面的例子中只有 pin 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::loop 中的迭代确实迭代了所有操作,如果我修改它:

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++ 初学者过度使用指针是一种常见的模式。很可能您应该使 container 成为对象的容器而不是指针,并利用自动内存管理而不是试图对抗它。

关于C++ 引用在函数范围内创建的实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53752096/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com