Vererbung verschieden Klassen mit einer Basisklasse



  • Hallo,

    Also folgendes, ich hab eine Basis Klasse GameState:

    #pragma once
    #include <SFML\Graphics.hpp>
    
    class GameStateManager;
    
    class GameState
    {
    public:
    	GameState();
    	~GameState();
    
    	virtual void Init();
    	virtual void Update(sf::RenderWindow &window, GameStateManager &game);
    	virtual void Render(sf::RenderWindow &window, GameStateManager &game);
    	virtual void Cleanup();
    
    	friend bool operator==(GameState const& left, GameState const& right) { return false; };
    	friend bool operator==(GameState const& left, int const& ID) {
    		if (left.ID == ID)
    			return true;
    
    		return false;
    	};
    
    protected:
    	int ID;
    };
    

    Dann hab ich noch mehrere Klassen die von dieser Klasse erben und in einer Klasse GameStateManager möchte ich Objekte dieser Klassen die ja alle die gleich Basis Klasse haben in einer Liste speichern.
    Das klappt auch eigentlich aber wenn ich eine der funktionen der Basisklasse aufrufe wird nie die überschriebene Funktion in der erbenden Klasse aufgerufen sondern nur die der Basisklasse.
    Kann mir jemand sagen was ich machen muss damit die überschriebene Funktion aufgerufen wird?

    LogoState:

    #pragma once
    #include "GameState.h"
    
    class LogoState :
    	public GameState
    {
    public:
    	LogoState();
    	~LogoState();
    
    	void Init() override;
    	void Update(sf::RenderWindow &window, GameStateManager &game) override;
    	void Render(sf::RenderWindow &window, GameStateManager &game) override;
    	void Cleanup() override;
    
    };
    

    GameStateManager:

    #pragma once
    
    #include <list>
    #include <algorithm>
    #include <SFML\Graphics.hpp>
    
    #include "GameState.h"
    
    class GameStateManager
    {
    public:
    	GameStateManager(sf::RenderWindow &window);
    	~GameStateManager();
    
    	void Init();
    	void Update(sf::RenderWindow &window);
    	void Render(sf::RenderWindow &window);
    	void Cleanup();
    
    	void AddState(GameState state);
    	void RemoveState(int ID);
    	void EnterState(int ID);
    	void Start();
    
    private:
    	std::list<GameState> gameStates;
    	sf::RenderWindow &window;
    	GameState currentState;
    };
    

    Gruß Erik



  • Stichwort: slicing.
    In kurz: Wenn du ein polymorphes Objekt by-value an etwas übergibst, wird bei der Kopie der abgeleitete Teil weggelassen, so dass das Objekt danach ein Objekt dann vom Typ der Basisklasse ist, nicht mehr der abgeleiteten
    Lösung: Polymorphe Objekte in Pointern im Container speichern (wieso eig. list?) und by value übergeben. Zusätzlich copy und move verbieten/Basisklasse abstrackt machen, dann meckert der Compiler sobald so etwas vorkommt.



  • Okay danke für die Antwort.
    Zuerst, was spricht denn gegen list?

    Dann, wie meinst du das mit copy und move verbieten und die Basisklasse abstrakt machen?



  • List ist relativ langsam im Gegensatz zu z.B. vector. Die Frage sollte dabei eher lauten, was spricht gegen vector.

    Wenn dein Compiler C++11 unterstützt kannst du das hier machen:

    class GameState
    {
    public:
        GameState();
        virtual ~GameState(); //muss auf jedenfall hier hin, wenn du Vererbung/Polymorphie nutzt
    
    	GameState(GameState const&) = delete;
    	GameState& operator=(GameState) = delete;
    
    	GameState(GameState&&)= delete;
    	GameState& operator=(GameState&&) = delete;
    };
    

    Ansonsten:

    class GameState
    {
    public:
        GameState();
        virtual ~GameState(); //muss auf jedenfall hier hin, wenn du Vererbung/Polymorphie nutzt
    
    private:
    	GameState(GameState const&);
    	GameState& operator=(GameState);
    
    	GameState(GameState&&);
    	GameState& operator=(GameState&&);
    };
    

  • Mod

    GameState(GameState&&)= delete;
        GameState& operator=(GameState&&) = delete;
    

    Ist nicht nötig. Im zweiten Beispiel genausowenig.

    §12.8 Abschnitt 9 und 20 schrieb:

    If the definition of a class X does not explicitly declare a move constructor, one will be implicitly declared as defaulted if and only if
    — X does not have a user-declared copy constructor
    [..]
    If the definition of a class X does not explicitly declare a move assignment operator, one will be implicitly declared as defaulted if and only if
    — X does not have a user-declared copy constructor



  • SFML bietet auch die Klasse sf::NonCopyable: http://www.sfml-dev.org/documentation/2.1/classsf_1_1NonCopyable.php



  • Aber wenn ich vector benutze muss ich doch im vorraus die größe festlegen, ich weiß aber ja nicht wie viele GameStates ich brauchen werde deswegen hatte ich mich für die List entschieden.

    okay also reicht es wenn ich von sf::NonCopyable erbe und im vector / in der liste nen pointer speicher?

    Edit:
    Aber warum sollte die Klasse NonCopyable sein?


  • Mod

    Aber wenn ich vector benutze muss ich doch im v****** die größe festlegen

    Nein, musst du nicht.



  • 0_o warum ist "vorraus" mit * ersetzt worden?

    okay dann nehm ich vector


  • Mod

    darman96 schrieb:

    0_o warum ist "v******" mit * ersetzt worden?

    Weil du "Voraus" falsch geschrieben hast.


Log in to reply