2009-05-15 8 views
0

クラスにテンプレート化された汎用メニューボタンクラスを作成しようとしていますので、どのボタンでもこのボタンを作成できます。そのクラスの異なる関数へのvoid関数ポインタを作成したいので、New Gameボタンをクリックすると、NewGame()関数などが呼び出されます。テンプレートクラスの関数ポインタを設定する際の問題

私はまだ少しのアイデアです関数ポインタを作成し、いくつかのアドバイスが必要です。

このメンバボタンを使用してコードをコンパイルしようとするたびに、狂ったリンクエラーが発生します。ここ

は誤りである:ここでは

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にコンパイルされます。しかし、SetButtonDrawのメソッドは、リンク時には、titlescreen.cppまたはそれに含まれるファイル.hに定義されていないため、欠落しています。 MenuButton.cppにはMENUBUTTON<TitleScreen>が必要ないため、MenuButton.oにも含まれません。

+0

ありがとう、私はC++のテンプレートクラスを理解していると思います。 –

0

最初の答えを明確にするために、ヘッダーで宣言されたテンプレートクラスをコンパイル済みの翻訳単位(つまり.cppファイル)で実装することはできません。ヘッダーにすべてのコードを入れる必要があります。最初のクラス宣言にすべてを入れるか、 "inline"を使用してクラスを最初に宣言してから、さらに特定の関数をヘッダの下に実装します。

0

ここではテンプレートが必要な理由は何ですか? プレーンな古い仮想関数またはメンバへのポインタが行います。 これはCommand Design Patternの完璧なアプリケーションになります。 テンプレートでは、のコンパイル時の多型が表示されますが、ここでは実行時の多型を探しています。

+0

私は何かを実装する前に、来週このことを確かめます。 –

関連する問題