未定义对构造函数的引用,即使构造函数是默认的并且所有内容都正确链接

问题描述 投票:0回答:1

我是 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++ 错误,这就是我在这里问的原因。有什么帮助吗?

c++ linker-errors undefined-reference
1个回答
0
投票

这里:

mainGamepad.buttons.at(Input::ButtonA).isPressed

您正在通过

at
呼叫
std::map<ButtonType,Button>

at
方法要求
Button
是默认可构造的,因为当找不到给定键的元素时,将插入默认构造(并返回引用)。

您的

Button
没有默认构造函数。

std::map::at
std::operator[]
不是简单的元素查找。它们是查找,如果没有找到则插入,并返回引用。只能通过
std::map
来查找
std::map::find
中的元素。

© www.soinside.com 2019 - 2024. All rights reserved.