Наследование / Полиморфизм - вызывающий метод подкласса - PullRequest
0 голосов
/ 30 марта 2012

В следующем, как я могу сделать так, чтобы программа использовала метод draw из MainMenuScreen вместо метода из GameScreen?

class GameScreen {
public:
    virtual void GameScreen::draw() {
        cout << "Drawing the wrong one..." << endl;
    }
};

class MainMenuScreen : public GameScreen {
public:
    void MainMenuScreen::draw() {
        cout << "Drawing the right one..." << endl;
    }
};

class ScreenManager {
public:
    list<GameScreen> screens;

    // assume a MainMenuScreen gets added to the list

    void ScreenManager::draw()
    {
        for ( list<GameScreen>::iterator screen = screens.begin(); 
              screen != screens.end(); screen++ )
        {
            screen->draw(); /* here it uses the draw method from GameScreen, 
                               but I want it to use the draw method from              
                               MainMenuScreen */
        }
    }
};

PS: я не хочусделать GameScreen::draw чисто виртуальным, поэтому предложите что-нибудь еще.

Ответы [ 3 ]

5 голосов
/ 30 марта 2012

как сделать так, чтобы программа использовала метод рисования из MainMenuScreen вместо метода из GameScreen?

Вы не можете, если вы не вызовете его по указателю илиссылка, фактический тип которой MainMenuScreen.

 list<GameScreen> screens;

, объявляет list объектов, а не указателей или ссылок.Если вы добавите MainMenuScreen объекты к нему, они потеряют информацию о типе из-за среза объекта , и полиморфизм не будет работать.Вам нужно:

 list<GameScreen*> screens;

или, еще лучше:

 list<shared_ptr<GameScreen> > screens;
2 голосов
/ 30 марта 2012

Вы не хотите делать draw чистым виртуальным, но вы действительно хотите сделать его (или оставить его) виртуальным.Для этого нужно сделать screens список из указателей (или, возможно, умных указателей) в GameScreen с, а не список GameScreen объектов.

Как и сейчас, когда вы (пытаетесь) вставить свой объект MainMenuScreen в список, он «нарезается», чтобы фактически стать a GameScreen объектом - поэтому, когда вы идетеваш список, вы ходите по списку объектов, все действительные типы которых GameScreen;надеяться получить MainMenuScreen поведение от любого из них в этот момент бесполезно.

Со списком указателей MainMenuScreen останется именно таким, поэтому при вызове вашей виртуальной функции вы получитеповедение фактического типа.

1 голос
/ 30 марта 2012

Вы стали жертвой нарезки объектов .Объекты в вашем списке являются только копиями объектов, которые вы в него вставили, и по мере того, как каждая копия была сделана, она переводилась в содержащийся тип.

Способ обойти это - вставить указатели (предпочтительно умные указатели, такие какshared_ptr) в список.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...