父类型的继承容器不能容纳子项?

时间:2014-09-21 19:30:54

标签: c++ inheritance vector casting

我有一个父菜单类和子菜单MainMenu,SettingsMenu,PauseMenu等。

我希望能够将它们全部放在矢量中......

我能做到

std::vector<Menu*> myVector;

然后当我在向量中按下

时对每个进行类型转换
pMainMenu = new MainMenu;
myVector.push_back((Menu*)pMainMenu);

并且它编译但是某些东西不能正常工作......

它不一定是矢量,但我希望能够遍历它们。

我总是试图实施Observer模式,并且我在该领域也遇到了继承困难!


对于Observer模式,我有一个Observer类,Game继承了Observer。我有一个由InputComponent继承的Subject类。 Subject有一个名为vObserver的Observer *向量和一个名为addObserver(Observer * observer)的函数,并在vObserver中添加传递的指针。我还有一个名为Notify(事件e)的函数,它通过vObserver进行迭代并调用它们的onNotify函数。

所以在Game中,我有一个名为inputComp的InputComponent实例。我做inputComp.addObserver(this)和inputComp.vObserver.size()是1.好。我在InputComponent中调用了Notify,但是当它执行时,Subject中的vObserver.size是0 ... idk我做错了什么

编辑:

class Menu
{
public:
    virtual void draw() = 0;
    virtual void onMouseMove(int x, int y) = 0;
    virtual void onMouseButton(int button, bool is_down) = 0;
    friend class InputComponent;
    friend class MainMenuInputComponent;
protected:
    SDL_Renderer* _renderer;
    std::vector<Button> vButton;
    std::vector<SDL_Texture *> vTexture;
};

class MainMenu :  public Menu
{
public:
    MainMenu(SDL_Renderer* renderer);
    virtual void draw();
    virtual void onMouseMove(int x, int y);
    virtual void onMouseButton(int button, bool is_down);
    friend class MainMenuInputComponent;
};



class InputComponent: public Subject
{
public:
    virtual void processInput()
    {}
    static bool isMouseWithin(int mouseX, int mouseY, SDL_Rect rect)
    {
        if (mouseX >= rect.x && mouseX <= rect.x + rect.w && mouseY >= rect.y && mouseY <= rect.y + rect.h)
            return true;
        else
            return false;
    }
};

class MainMenuInputComponent : public InputComponent
{
public:
    MainMenuInputComponent(MainMenu* owner)
        :_owner(owner){}
    virtual void processInput();
    virtual void onBtnClick(std::string btnName);

    MainMenu* _owner;
};

class Game : public Observer
{
public:

Game();
void initSDL();
void initGame();
void processGameInput();
void renderGame();
void update();
virtual void onNotify(Events e);

SDL_Window* myWindow;
SDL_Renderer* myRenderer;
std::vector<MainMenuInputComponent> vInputComponent;
std::stack<MainMenu*> menuStack;
};


Game::Game()
{
    initSDL();
    initGame();
}

void Game::initGame()
{
    //Create the Main Menu
    MainMenu* pMainMenu = new MainMenu(myRenderer);
    //Add menu to the stack
    menuStack.push((pMainMenu));
        //Add it's components to respective arrays
    MainMenuInputComponent inputComp = MainMenuInputComponent(pMainMenu);
    vInputComponent.push_back(inputComp);
        //Add Observer/Subject relationship.
    inputComp.addObserver((Observer*)this);
    int bob = (int)inputComp.vObserver.size(); //to see if size went up


}

void Game::processGameInput()
{
    if (!menuStack.empty())
    {
        for (int i = 0; i < (int)vInputComponent.size(); i++)
        {
            //Menu* compOwner = (Menu*)(vInputComponent[i]._owner);
            //std::unique_ptr<Menu, std::default_delete<Menu>> a = menuStack.top();
            if ((vInputComponent[i]._owner) == menuStack.top())
            {
                vInputComponent[i].processInput();
            }
            //vInputComponent[i].processInput();
        }
    }
    else
    for (int i = 0; i < (int)vInputComponent.size(); i++)
    {
        vInputComponent[i].processInput();
    }
}

void Game::renderGame()
{
    SDL_RenderClear(myRenderer);
    MainMenu* bob = menuStack.top();
    if (!menuStack.empty())
        (menuStack.top())->draw();
    SDL_RenderPresent(myRenderer);
}

void Game::onNotify(Events event)
{
    switch (event)
    {
    case POP_MENU:
        menuStack.pop();
        break;
    case GOTO_SETTINGS:
        //Menu* pSettingsMenu =(Menu*)(new SettingsMenu(myRenderer));
        //menuStack.push(std::unique_ptr<Menu>(pSettingsMenu));
        break;
        // Handle other events, and update heroIsOnBridge_...
    }
}

class Subject
{
public:
    void addObserver(Observer* observer)
    {
        vObserver.push_back(observer);
    }

    void removeObserver(Observer* observer)
    {
        //vObserver.erase(std::find(vObserver.begin(), vObserver.end(), 8));
    }


    std::vector<Observer*> vObserver;
protected:
    void notify(Events e)
    {
        for (int i = 0; i < (int)vObserver.size(); i++)
        {
            vObserver[i]->onNotify(e);
        }
    }
};

class Observer
{
public:
    virtual ~Observer() {}

    virtual void onNotify(Events e) = 0;
};

1 个答案:

答案 0 :(得分:1)

如果MainMenu公开地继承自Menu,那么您甚至不需要输入指向MainMenuMenu的指针。也就是说,这应该有效:

class Menu {};
class MainMenu : public Menu {};

std::vector<Menu*> myVector;
MainMenu* pMainMenu = // ...
myVector.push_back(pMainMenu);

但是,您真正应该做的是使用shared_ptrunique_ptr之类的内容。这是一个更完整的示例,使用shared_ptr

#include <vector>
#include <memory>
#include <iostream>

class Menu
{
public:
    virtual void on_event() = 0;
    // virtual destructor needed for polymorphic base classes
    virtual ~Menu() {}
};

class MainMenu : public Menu
{
public:
    virtual void on_event()
    {
        std::cout << "Hello world! from MainMenu" << std::endl;
    }
};

class PauseMenu : public Menu
{
public:
    virtual void on_event()
    {
        std::cout << "Hello world! from PauseMenu" << std::endl;
    }
};

class SettingsMenu : public Menu
{
public:
    virtual void on_event()
    {
        std::cout << "Hello world! from SettingsMenu" << std::endl;
    }
};

int main()
{
    std::vector<std::shared_ptr<Menu>> myVector;
    myVector.push_back(std::make_shared<MainMenu>());
    myVector.push_back(std::make_shared<PauseMenu>());
    myVector.push_back(std::make_shared<SettingsMenu>());
    for(auto& menu : myVector) {
        menu->on_event();
    }
    return 0;
}

预期产出:

Hello world! from MainMenu
Hello world! from PauseMenu
Hello world! from SettingsMenu

这也应该有效,并为您提供为您提供内存管理的额外功能。