2009-05-15 4 views
0

모든 클래스에서이 단추를 만들 수 있도록 클래스에 템플릿 화 된 일반 메뉴 단추 클래스를 만들려고합니다. 그 클래스의 다른 함수에 void 함수 포인터를 만들고 싶습니다. 그래서 New Game 버튼을 클릭하면 NewGame() 함수 등을 호출 할 것입니다.템플릿 클래스의 함수 포인터 설정 문제

저는 아직 아이디어가 조금 새롭습니다. 함수 포인터를 만들고 몇 가지 조언을 원합니다.

이 Menubutton으로 코드를 컴파일 할 때마다 미친 링크 오류가 발생합니다.

Error 1 error LNK2019: unresolved external symbol "public: void __thiscall MENUBUTTON::Draw(void)" ([email protected][email protected]@@@@QAEXXZ) referenced in function "public: virtual void __thiscall TitleScreen::Draw(void)" ([email protected]@@UAEXXZ) TitleScreen.obj

MenuButton.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(); 
}; 

MenuButton.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; 

} 

다음 메뉴 버튼을 사용하고 내 타이틀 화면입니다 : 여기

는 오류입니다.

TitleScreen.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(); 
}; 

TitleScreen.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(); 
} 

도와주세요! :)

답변

1

링크 오류를 제거하려면 template으로 시작하는 모든 메서드 정의를 .cpp 파일에서 .h 파일로 이동하십시오. 당신의 코드에서 이러한 이동 :

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

.cpp 파일과 함께 작동하지 않는 이유는 컴파일러가 MENUBUTTON<Foo>MENUBUTTON<Bar> 등 다른 클래스를 취급하고 생성하고 이러한 클래스 때마다 컴파일한다는 것입니다 사용. 따라서 titlescreen.cpp을 컴파일 할 때 MENUBUTTON<TitleScreen>을 사용하면 MENUBUTTON<TitleScreen> 코드가 오브젝트 파일 titlescreen.o으로 컴파일됩니다. 그러나 SetButtonDrawtitlescreen.cpp 또는 이에 포함 된 .h 파일에 정의되어 있지 않기 때문에 링크 할 때 누락됩니다. MenuButton.cpp에는 MENUBUTTON<TitleScreen>이 필요하지 않으므로 MenuButton.o에 포함되지 않습니다.

+0

감사합니다. 저는 C++의 템플릿 클래스를 더 잘 이해한다고 생각합니다. –

0

첫 번째 대답을 명확히하기 위해 헤더에 선언 된 템플릿 클래스를 가질 수 없으며 분리 된 컴파일 된 번역 단위 (예 : .cpp 파일)로 구현됩니다. 헤더에 모든 코드를 넣어야합니다. 초기 클래스 선언에 모두 넣을 수도 있고, "inline"을 사용하여 클래스를 먼저 함수로 선언 한 다음 헤더에서 더 구체적인 함수를 구현할 수도 있습니다.

0

더 좋은 방법이라고 말하면 왜 여기에 템플릿이 필요합니까? 일반 오래된 가상 함수 또는 멤버에 대한 포인터가 수행합니다. 이것은 Command Design Pattern의 완벽한 응용 프로그램입니다. 템플릿은 의 컴파일 타임 다형성을 제공하지만 여기서는 런타임 다형성을 찾고 있습니다.

+0

나는 무엇이든 구현하기 전에 다음 주를 확실히 살펴볼 것입니다. –