gpt4 book ai didi

c++ - 在模板类中设置函数指针的问题

转载 作者:行者123 更新时间:2023-11-28 08:33:13 28 4
gpt4 key购买 nike

我正在尝试创建一个模板化为类的通用菜单按钮类,因此我可以在任何类中制作此按钮。我想创建一个指向该类中不同函数的 void 函数指针,因此当您单击 New Game 按钮时,它将调用 NewGame() 函数等。

我对创建函数指针的想法还是有点陌生​​,希望得到一些建议。

每次我尝试使用此菜单按钮编译我的代码时,我都会遇到一个疯狂的链接错误。

这里是错误:

Error 1 error LNK2019: unresolved external symbol "public: void __thiscall MENUBUTTON::Draw(void)" (?Draw@?$MENUBUTTON@VTitleScreen@@@@QAEXXZ) referenced in function "public: virtual void __thiscall TitleScreen::Draw(void)" (?Draw@TitleScreen@@UAEXXZ) TitleScreen.obj

菜单按钮.h

template <class t>
struct MENUBUTTON
{
SPRITE Normal; // Sprite to display when not hovered over or pressed down
SPRITE Hover; // Sprite to display when hovered over
RECTANGLE HoverBounds; // The Rectangle that activates the hover flag

t* pClass; // Pointer to the templated class
void (t::*ClickFunction)(); // Pointer to void function

void SetButton(int xPos, int yPos, int width, int height, int hPadLeft, int hPadTop, int hWidth, int hHeight, LPCTSTR normalFilePath, LPCTSTR hoverFilePath, t* objectClass, void (t::*ClickFunction)());

bool IsMouseHover();

void CheckPressed();

void Draw();
};

菜单按钮.cpp

#include "Global.h"

template <class t>
void MENUBUTTON<t>::SetButton(int xPos, int yPos, int width, int height, int hPadLeft, int hPadTop, int hWidth, int hHeight, LPCTSTR normalFilePath, LPCTSTR hoverFilePath, t* objectClass, void (t::*ClickFunction)())
{
// Position
Hover.position.x = Normal.position.x = xPos;
Hover.position.y = Normal.position.y = yPos;
Hover.position.z = Normal.position.z = 0;

// Width / Height
Hover.width = Normal.width = width;
Hover.height = Normal.height = height;

// Hover RECTANGLE
HoverBounds.x = xPos + hPadLeft;
HoverBounds.y = yPos + hPadTop;
HoverBounds.width = hWidth;
HoverBounds.height = hHeight;

// Load the Sprites
LoadSprite(&Normal, normalFilePath, width, height, 1, 1);
LoadSprite(&Hover, hoverFilePath, width, height, 1, 1);

// Set the Click function pointer
this->pClass = objectClass;
this->ClickFunction = ClickFunction;
}

template <class t>
void MENUBUTTON<t>::Draw()
{
if(IsMouseHover())
{
DrawSprite(&Hover, 0, Hover.position.x, Hover.position.y, Hover.position.z);
}
else
{
DrawSprite(&Normal, 0, Normal.position.x, Normal.position.y, Normal.position.z);
}
}

template <class t>
bool MENUBUTTON<t>::IsMouseHover()
{
return (((InputData.MousePosition.x >= HoverBounds.x) && (InputData.MousePosition.x <= (HoverBounds.x + HoverBounds.width))) &&
((InputData.MousePosition.y >= HoverBounds.y) && (InputData.MousePosition.y <= (HoverBounds.y + HoverBounds.height)))) ? true : false;

}

这是我使用菜单按钮的标题屏幕。

标题屏幕.h

class TitleScreen : public BaseState
{
// SPRITES
SPRITE titleScreenBG;

// MENU BUTTONS
MENUBUTTON<TitleScreen> playButton;
MENUBUTTON<TitleScreen> quitButton;

public:
TitleScreen();

virtual void Initialize();
virtual void End();

virtual void Update(float dt, INPUTDATA* input);
virtual void Draw();

void QuitGame();

void NewGame();
};

标题屏幕.cpp

#include "Global.h"

// Constructors
TitleScreen::TitleScreen()
{

}

// Virtual Voids
void TitleScreen::End()
{

}

void TitleScreen::Initialize()
{
this->Enabled = true;
this->Visible = true;

// Initialize sprites
ZeroMemory(&titleScreenBG, sizeof(SPRITE));
LoadSprite(&titleScreenBG, TEXT("../../PNG/TitleScreenBG.png"), 1440, 900, 1, 1);
titleScreenBG.position.x = titleScreenBG.position.y = titleScreenBG.position.z = 0;

// Initialize buttons
ZeroMemory(&playButton, sizeof(MENUBUTTON<TitleScreen>));
playButton.SetButton(55, 170, // x , y
512, 128, // width, height
10, 10, // Left, Top Padding
400, 70, // Hover width, Hover height
TEXT("../../PNG/NewGame.png"), TEXT("../../PNG/NewGameH.png"),
this, &TitleScreen::NewGame);

ZeroMemory(&quitButton, sizeof(MENUBUTTON<TitleScreen>));
quitButton.SetButton(55, 240, // x , y
512, 128, // width, height
10, 10, // Left, Top Padding
190, 70, // Hover width, Hover height
TEXT("../../PNG/QuitButton.png"), TEXT("../../PNG/QuitButtonH.png"),
this, &TitleScreen::QuitGame);
}

void TitleScreen::Update(float dt, INPUTDATA* input)
{

}

void TitleScreen::Draw()
{
StartRender();
DrawSprite(&titleScreenBG, 0, titleScreenBG.position.x, titleScreenBG.position.y, titleScreenBG.position.z);
playButton.Draw();
quitButton.Draw();
EndRender();
}

// Public Methods
void TitleScreen::QuitGame()
{
CloseDirect3D();
}

void TitleScreen::NewGame()
{
CloseDirect3D();
}

如果有人对我如何以不同的方式为任何情况使按钮动态化有任何建议,或者知道这是什么问题,请帮忙! :)

最佳答案

要消除链接错误,请移动所有以 template 开头的方法定义来自 .cpp文件到 .h文件。在您的代码中,移动这些:

template <class t> void MENUBUTTON<t>::SetButton ... { ... }
template <class t> void MENUBUTTON<t>::Draw ... { ... }

它不适用于 .cpp 的原因file 是编译器对待 MENUBUTTON<Foo>MENUBUTTON<Bar> etc. 作为不同的类,并且它在使用时生成并编译这样一个类。所以如果你使用 MENUBUTTON<TitleScreen>编译时 titlescreen.cpp , 然后是 MENUBUTTON<TitleScreen>代码将被编译到目标文件中titlescreen.o .但是方法SetButtonDraw将在链接时丢失,因为它们未在 titlescreen.cpp 中定义或任何 .h它包含的文件。 MenuButton.o也不会包含它,因为 MenuButton.cpp不需要 MENUBUTTON<TitleScreen> .

关于c++ - 在模板类中设置函数指针的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/870794/

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