我有一个父菜单类和子菜单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;
};
答案 0 :(得分:1)
如果MainMenu
公开地继承自Menu
,那么您甚至不需要输入指向MainMenu
至Menu
的指针。也就是说,这应该有效:
class Menu {};
class MainMenu : public Menu {};
std::vector<Menu*> myVector;
MainMenu* pMainMenu = // ...
myVector.push_back(pMainMenu);
但是,您真正应该做的是使用shared_ptr
或unique_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
这也应该有效,并为您提供为您提供内存管理的额外功能。