2014-09-21 75 views
1

我有一个父菜单类和儿童的MainMenu,SettingsMenu,PauseMenu等父类型的继承容器不能容纳子项?

我希望能够保持他们都在一个载体...

我可以做

std::vector<Menu*> myVector; 

,然后强制转换每一个当我在矢量

pMainMenu = new MainMenu; 
myVector.push_back((Menu*)pMainMenu); 

的push_back,它编译,但东西不工作正确的道路......

它不一定是一个向量,但我想能够遍历它们。

我总是试图实现Observer模式,并且在继承方面也遇到了困难!


对于观察者模式,我有一个观察者类和游戏继承观察者。我有一个由InputComponent继承的Subject类。 Subject有一个叫做vObserver的Observer *矢量和一个名为addObserver(Observer * observer)的函数,并将传入的指针添加到vObserver中。我还有一个名为Notify(event e)的函数,它通过vObserver迭代并调用onNotify函数。

所以在游戏中,我有一个名为inputComp的InputComponent实例。我做inputComp.addObserver(this)和inputComp.vObserver.size()是1.很好。我有一个呼叫InputComponent通知哪一个没有被触发,但在执行时,里面的主题是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

你是[切片对象]的受害者(http://stackoverflow.com/questions/274626/what-is-the-slicing-problem-in-c)? – 2014-09-21 19:34:37

+0

是的,就像那样...当我做std :: vector 它的工作,但这是愚蠢的,因为我不会有多个MainMenu ...!该怎么办? – user1420563 2014-09-21 19:48:17

+1

_ @ user1420563_请不要尝试通过其他评论改进您的帖子。只需放置一个水平栏并将此信息添加到您的问题。 – 2014-09-21 20:01:29

回答

1

如果MainMenu公开继承Menu,那么你甚至不需要输入指向MainMenu的指针到Menu。也就是说,这应该工作:

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 

这也应该工作,并为您的照顾内存管理你的奖金功能。

+0

我正在使用unique_ptr,实际上不同的菜单是在一个堆栈中,但由于某种原因,当我做了myStack.top() - > functionCall()它给了我一个奇怪的内存错误。 我尝试了一下myStack.top()究竟是什么,所以我创建了一个变量并将其分配给该变量,以便我可以在调试器中查看它的值,但它说了一些沿着我尝试访问的行的内容被删除的函数或其他东西。 所以我只是使用普通的指针,它摆脱了 – user1420563 2014-09-21 19:42:50

+0

@ user1420563:如果你的'Menu'在堆栈中,那么你为什么在你的问题中有'pMainMenu = new MainMenu'?你能否更新你的问题来反映你的实际情况?默认情况下,'shared_ptr'和'unique_ptr'将处理你的指针,就像它们指向动态存储一样,而不是堆栈对象,这可能解释了你为什么看到错误。 – 2014-09-21 19:51:25

+0

是保持谢谢:) – user1420563 2014-09-21 20:00:40