C++;派生类问题 我正在用C++做游戏,我的派生类有问题。我有一个名为GameScreen的基类,它有一个vitrual void draw()函数,没有任何语句。我还有一个名为MenuScreen的派生类,它也有一个虚拟的void draw()函数,还有一个名为TestMenu的MenuScreen派生类,它也有一个void draw()函数。在我的程序中,我有一个游戏屏幕列表,我有一个游戏屏幕迭代器通过调用每个游戏屏幕draw()函数

C++;派生类问题 我正在用C++做游戏,我的派生类有问题。我有一个名为GameScreen的基类,它有一个vitrual void draw()函数,没有任何语句。我还有一个名为MenuScreen的派生类,它也有一个虚拟的void draw()函数,还有一个名为TestMenu的MenuScreen派生类,它也有一个void draw()函数。在我的程序中,我有一个游戏屏幕列表,我有一个游戏屏幕迭代器通过调用每个游戏屏幕draw()函数,c++,inheritance,C++,Inheritance,问题是我在游戏屏幕列表中放置了一个TestMenu对象。它不是调用TestMenu的draw()函数的迭代器,而是调用GameScreen类的draw()函数。有人知道我如何调用TestMenu的draw()函数而不是GameScreen中的函数吗 以下是函数: // Tell each screen to draw itself. //gsElement is a GameScreen iterator //gsScreens is a list of type GameScreen

问题是我在游戏屏幕列表中放置了一个TestMenu对象。它不是调用TestMenu的draw()函数的迭代器,而是调用GameScreen类的draw()函数。有人知道我如何调用TestMenu的draw()函数而不是GameScreen中的函数吗

以下是函数:

// Tell each screen to draw itself.
//gsElement is a GameScreen iterator
    //gsScreens is a list of type GameScreen
void Draw()
{
    for (gsElement = gsScreens.begin(); gsElement != gsScreens.end(); gsElement++)
    {
        /*if (gsElement->ssState == Hidden)
            continue;*/

        gsElement->Draw();
    }
}   
以下是我的课程:

class GameScreen {
public:
    string strName;
    bool bIsPopup;
    bool bOtherScreenHasFocus;
    ScreenState ssState;
    //ScreenManager smScreenManager;

    GameScreen(string strName){
        this->strName = strName;
    }

    //Determine if the screen should be drawn or not
    bool IsActive(){
        return !bOtherScreenHasFocus && 
            (ssState == Active);
    }

    //------------------------------------
    //Load graphics content for the screen
    //------------------------------------
    virtual void LoadContent(){
    }

    //------------------------------------
    //Unload content for the screen
    //------------------------------------
    virtual void UnloadContent(){
    }

    //-------------------------------------------------------------------------
    //Update changes whether the screen should be updated or not and sets
    //whether the screen should be drawn or not.
    //
    //Input:
    //  bOtherScreenHasFocus - is used set whether the screen should update
    //  bCoveredByOtherScreen - is used to set whether the screen is drawn or not
    //-------------------------------------------------------------------------
    virtual void Update(bool bOtherScreenHasFocus, bool bCoveredByOtherScreen){
        this->bOtherScreenHasFocus = bOtherScreenHasFocus;

        //if the screen is covered by another than change the screen state to hidden
        //else set the screen state to active
        if(bCoveredByOtherScreen){
            ssState = Hidden;
        }
        else{
            ssState = Active;
        }
    }

    //-----------------------------------------------------------
    //Takes input from the mouse and calls appropriate actions
    //-----------------------------------------------------------
    virtual void HandleInput(){
    }

    //----------------------
    //Draw content on screen
    //----------------------
    virtual void Draw(){
    }

    //--------------------------------------
    //Deletes screen from the screen manager
    //--------------------------------------
    void ExitScreen(){
        //smScreenManager.RemoveScreen(*this);
    }
};

class MenuScreen: public GameScreen{
public:
    vector <BUTTON> vbtnMenuEntries; 

    MenuScreen(string strName):GameScreen(strName){
    }

    virtual void Update(bool bOtherScreenHasFocus, bool bCoveredByOtherScreen){
        GameScreen::Update(bOtherScreenHasFocus, bCoveredByOtherScreen);

        for(unsigned int i = 0; i < vbtnMenuEntries.size(); i++){
            vbtnMenuEntries[i].IsPressed();
        }
    }

    virtual void Draw(){
        GameScreen::Draw();

        for(unsigned int i = 0; i < vbtnMenuEntries.size(); i++)
            vbtnMenuEntries[i].Draw();
    }

};

class testMenu : public MenuScreen{
public:
    vector<OBJECT> test;
    //OBJECT background3();
//  OBJECT testPic(512, 384, buttonHover.png, 100, 40, 100, 40);
//  BUTTON x(256, 384, buttonNormal.png, buttonHover.png, buttonPressed.png, 100, 40, test());
    bool draw;

    testMenu():MenuScreen("testMenu"){
        OBJECT background3(1, 1, 0, TEXT("background.png"), 1, 1, 1024, 768);
        OBJECT testPic(512, 384,0, TEXT("buttonHover.png"), 1, 1, 100, 40);
        test.push_back(background3);
        test.push_back(testPic);
        //background3.Init(int xLoc, int yLoc, int zLoc, LPCTSTR filePath, int Rows, int Cols, int Width, int Height)
        //test.push_back(background3);
    //  vbtnMenuEntries.push_back(x);
        draw = false;
    }

    void Update(bool bOtherScreenHasFocus, bool bCoveredByOtherScreen){
        MenuScreen::Update(bOtherScreenHasFocus, bCoveredByOtherScreen);
        //cout << "X" << endl;
        /*if(MouseLButton == true){
            testMenu2 t;
            smManager.AddScreen(t);
        }*/
    }

    void Draw(){
        //background3.Draw();
        test[0].Draw();
        test[1].Draw();
        MenuScreen::Draw();
    ///*if(draw){*/
    //  testPic.Draw();
    //}
}

/*void test(){
    draw = true;
}*/

};
类游戏屏幕{
公众:
字符串strName;
布尔-比斯波;
布尔;哈斯福克斯;
屏幕状态ssState;
//屏幕管理器smScreenManager;
游戏屏幕(字符串strName){
这个->strName=strName;
}
//确定是否应绘制屏幕
bool IsActive(){
return!hasFocus&&
(ssState==活动);
}
//------------------------------------
//加载屏幕的图形内容
//------------------------------------
虚拟void LoadContent(){
}
//------------------------------------
//卸载屏幕的内容
//------------------------------------
虚拟内容{
}
//-------------------------------------------------------------------------
//更新更改是否应更新屏幕并设置
//是否绘制屏幕。
//
//输入:
//设置屏幕是否应该更新
//bCoveredByOtherScreen-用于设置是否绘制屏幕
//-------------------------------------------------------------------------
虚拟无效更新(bool屏幕聚焦,bool bCoveredByOtherScreen){
此->困扰屏幕聚焦=困扰屏幕聚焦;
//如果屏幕被另一个屏幕覆盖,则将屏幕状态更改为隐藏
//否则,将屏幕状态设置为“活动”
如果(b位于另一屏幕上){
ssState=隐藏;
}
否则{
ssState=活动状态;
}
}
//-----------------------------------------------------------
//从鼠标获取输入并调用适当的操作
//-----------------------------------------------------------
虚拟void HandleInput(){
}
//----------------------
//在屏幕上绘制内容
//----------------------
虚空绘制(){
}
//--------------------------------------
//从屏幕管理器中删除屏幕
//--------------------------------------
void ExitScreen(){
//smScreenManager.RemoveScreen(*此项);
}
};
类菜单屏幕:公共游戏屏幕{
公众:
向量向量向量;
菜单屏幕(字符串strName):游戏屏幕(strName){
}
虚拟无效更新(bool屏幕聚焦,bool bCoveredByOtherScreen){
游戏屏幕::更新(屏幕聚焦,bCoveredByOtherScreen);
for(无符号整数i=0;i//cout如果gsScreens是一个对象列表而不是指针列表(如代码所示),那么您并没有存储您认为存储在其中的内容

所发生的事情是——您实际上不是将TestMenu放入列表,而是使用编译器生成的复制构造函数构造一个新的MenuScreen,并将此MenuScreen放入列表


C++通过指针是多态的,因此如果没有指针,就不会有多态行为。

如果gsScreens是一个对象列表而不是指针列表(如代码所示),那么就没有存储您认为存储在其中的内容

所发生的事情是——您实际上不是将TestMenu放入列表,而是使用编译器生成的复制构造函数构造一个新的MenuScreen,并将此MenuScreen放入列表


C++通过指针是多态的,因此如果没有指针,就不会有多态行为。

要获得所追求的多态行为,同时使用
std::vector
,必须在向量中存储指向基类类型的指针,而不是存储值。此外,必须记住在如果向量超出范围

例如:

#include <vector>
#include <algorithm>

struct Base
{
    virtual void Foo() = 0;
    virtual ~Base() { }
};

struct Derived1 : public Base
{
    void Foo() { }
};

struct Derived2 : public Base
{
    void Foo() { }
};

struct delete_ptr
{
    template <typename T>
    void operator()(T& p)
    {
        delete p;
        p = 0;
    }
};

int wmain(int, wchar_t*[])
{
    std::vector<Base*> items;
    items.push_back(new Derived1);
    items.push_back(new Derived2);

    Base& first = items.front();
    first.Foo(); // Will boil down to Derived1::Foo().

    Base& last = items.back();
    last.Foo(); // Will boil down to Derived2::Foo().

    std::for_each(items.begin(), items.end(), delete_ptr())
};
#包括
#包括
结构基
{
虚拟void Foo()=0;
虚拟~Base(){}
};
结构派生1:公共基
{
void Foo(){}
};
结构派生2:公共基础
{
void Foo()
#define DISALLOW_COPYING(X) \
    private: \
        X(const X &); \
        const X& operator= (const X& x)
class Foo {
    // ...
    DISALLOW_COPYING(Foo);
};