我是 C++ 的初学者(做了一点点,但仍然相对较新),所以这可能是显而易见的事情,但我遇到了一个错误,我似乎无法在网上的任何地方找到解决方案。 我收到链接器错误:
Gamepad.o:(.rodata._ZTIN5Input11WiiUGamepadE[_ZTIN5Input11WiiUGamepadE]+0x8): 对 `_ZTIN5Input10ControllerE' 的未定义引用
我在 GameInput.hpp 中定义一个基本的 Controller 类和一个派生的 WiiUGamepad 类,并在 Gamepad.cpp 中为 WiiUGamepad 类添加一些额外的功能 两者都正确链接到应用程序,并且 Controller 和 WiiUGamepad 都没有构造函数(我也尝试过定义空构造函数,并使用 default 关键字。)并且两者都不起作用。 这是有问题的确切源代码:
游戏输入.hpp
#pragma once
#include <vector>
#include <map>
#include "vpad/input.h"
#include "datatypes.hpp"
namespace Input{
enum ButtonType{
ButtonB = 0,
ButtonA = 1,
ButtonX = 2,
ButtonY = 3,
ButtonStart = 4,
ButtonSelect = 5,
ButtonOne = 6,
ButtonTwo = 7,
ButtonL = 10,
ButtonR = 20,
ButtonZL = 11,
ButtonZR = 21,
};
const std::map<ButtonType,VPADButtons> ButtonTypeToVPAD = {
{ButtonA, VPAD_BUTTON_A},
{ButtonB, VPAD_BUTTON_B},
{ButtonX, VPAD_BUTTON_X},
{ButtonY, VPAD_BUTTON_Y},
{ButtonStart, VPAD_BUTTON_PLUS},
{ButtonSelect, VPAD_BUTTON_MINUS},
{ButtonL,VPAD_BUTTON_L},
{ButtonR,VPAD_BUTTON_R},
{ButtonZL,VPAD_BUTTON_ZL},
{ButtonZR,VPAD_BUTTON_ZR},
};
struct Button{
public:
ButtonType buttonType;
bool isPressed;
bool wasPressedLastFrame;
Button(ButtonType type){
buttonType = type;
}
bool wasJustPressed(){
return (isPressed && !wasPressedLastFrame);
}
};
enum AxisInputType{
AxisLeftStick = 0,
AxisRightStick = 1,
AxisDPAD = 2,
};
struct AxisInput2D{
AxisInputType axisType;
Vector2 value;
Vector2 change;
AxisInput2D(AxisInputType type){
axisType = type;
}
};
class Controller{ // Base class for all controller types.
public:
Controller() = default;
std::map<ButtonType,Button> buttons;
std::map<AxisInputType,AxisInput2D> axes;
virtual void processInput();
};
class WiiUGamepad : public Controller{ // Wii U Gamepad controller.
public:
std::map<ButtonType,Button> buttons = {
{ButtonA, Button(ButtonA)},
{ButtonB, Button(ButtonB)},
{ButtonX, Button(ButtonX)},
{ButtonY, Button(ButtonY)},
{ButtonL, Button(ButtonL)},
{ButtonR, Button(ButtonR)},
{ButtonZL, Button(ButtonZL)},
{ButtonZR, Button(ButtonZR)},
{ButtonSelect,Button(ButtonSelect)},
{ButtonStart,Button(ButtonStart)},
};
std::map<AxisInputType,AxisInput2D> axes = {
{AxisLeftStick,AxisInput2D(AxisLeftStick)},
{AxisRightStick,AxisInput2D(AxisRightStick)},
{AxisDPAD,AxisInput2D(AxisDPAD)},
};
void processInput() override;
};
}
游戏手柄.cpp
#include "GameInput.hpp"
#include "HelperStandard.hpp"
#include "vpad/input.h"
void Input::WiiUGamepad::processInput(){
VPADStatus* padStatuses = new VPADStatus();
VPADReadError readError;
if(VPADRead(VPAD_CHAN_0,padStatuses,16,&readError) == 0){
for(auto &[key, val] : buttons){
val.wasPressedLastFrame = val.isPressed;
val.isPressed = (padStatuses->hold & ButtonTypeToVPAD.at(val.buttonType)); // Check if button held.
}
} else {
switch (readError)
{
case VPAD_READ_SUCCESS:
print("VPAD Read Error: task failed successfuly.");
break;
case VPAD_READ_NO_SAMPLES:
print("VPAD Read Error: No new sample data to write.");
break;
case VPAD_READ_INVALID_CONTROLLER:
print("VPAD Read Error: Invalid Channel/Controller.");
break;
case VPAD_READ_BUSY:
print("VPAD Read Error: Channel busy - Likely accessed by another thread.");
break;
case VPAD_READ_UNINITIALIZED:
print("VPAD Read Error: Vpad is uninitialized. Please call VPADInit();");
break;
default:
print("VPAD Read Error: Unknown Error Reason");
break;
}
}
}
main.cpp(没有一长串头文件,但是 Gameinput.hpp 是#included)
int main(int argc, char **argv)
{
int result = 0;
romfsInit();
OSReport("main run\n");
WHBLogUdpInit();
WHBProcInit();
InitializeGraphics();
CamTabletRender MainRenderer = CamTabletRender();
std::vector<Sprite> tvSprites{};
Sprite tvSprite = Sprite("texture.tga");
tvSprites.push_back(tvSprite);
std::vector<Sprite> drcSprites{};
drcSprites.push_back(Sprite("testimage.tga"));
Input::WiiUGamepad mainGamepad;
while (WHBProcIsRunning()) {
mainGamepad.processInput();
if(mainGamepad.buttons.at(Input::ButtonA).isPressed)
{
tvSprite.position.x += 0.01;
}
WHBGfxBeginRender();
WHBGfxBeginRenderTV();
MainRenderer.Render(tvSprites);
WHBGfxFinishRenderTV();
WHBGfxBeginRenderDRC();
MainRenderer.Render(drcSprites);
WHBGfxFinishRenderDRC();
WHBGfxFinishRender();
}
WHBLogPrintf("Exiting...");
romfsExit();
WHBUnmountSdCard();
WHBGfxShutdown();
WHBProcShutdown();
WHBLogUdpDeinit();
return 0;
}
我还想指出,这只在我创建 WiiUGamepad 的新实例(main.cpp 中的 mainGamepad)时才会发生,因此构造函数肯定会发生一些奇怪的事情。 由于我使用的是一个有点晦涩的编译器/工具链或任何它被分类的东西,这可能是某种问题,但我相信这是一个标准的 C++ 错误,这就是我在这里问的原因。有什么帮助吗?
这里:
mainGamepad.buttons.at(Input::ButtonA).isPressed
您正在通过
at
呼叫 std::map<ButtonType,Button>
。
at
方法要求Button
是默认可构造的,因为当找不到给定键的元素时,将插入默认构造(并返回引用)。
您的
Button
没有默认构造函数。
std::map::at
和 std::operator[]
不是简单的元素查找。它们是查找,如果没有找到则插入,并返回引用。只能通过 std::map
来查找 std::map::find
中的元素。