Search code examples
c++polymorphismabstractvirtual-functionsderived

C++: Use pointer from abstract class for accessing method of derived classes; derived class apears to be abstract as well


I have looked for 2 hours now (mainly on this site) to understand my problem I have while coding in C++. I have a abstract base class which looks like this:

Screen.hpp

#include <SFML/Graphics.hpp>

class Screen {
public:
   virtual ~Screen();

   virtual void Init() const = 0;
   virtual void Render(sf::RenderWindow &window) const = 0;
   virtual void Update(sf::RenderWindow &window, sf::Time &deltaTime) const = 0;
   virtual void EventTriggered(sf::RenderWindow &window, sf::Event &event) const = 0;
};

Next I have declared a class which derives from the base class:

Splashscreen.hpp

#include "Screen.hpp"

class Splashscreen : public Screen {
public:
   Splashscreen();
   ~Splashscreen();

   void Init();
   void Update(sf::RenderWindow &window, sf::Time &deltaTime);
   void Render(sf::RenderWindow &window);
   void EventTriggered(sf::RenderWindow &window, sf::Event &event);

private:
   sf::Sprite *_splashSprite;
};

And finally I want to create a new Splashscreen object and assign the address to a pointer from the base class:

void Game::Init() {
   Screen* ptrScreen = new Splashscreen;
   _displayMgr.AddScreen("Splash", ptrScreen);
   _displayMgr.ChangeScreen("Splash");
}

As I mentioned before, I looked this problem up already and found a ton of solutions and came up with this what I have now. But I still get an error in the line

Screen* ptrScreen = new Splashscreen;

while compiling that says following:

error: invalid new-expression of abstract class type 'Splashscreen'

I just don't understand this, because I have defined all declared methods that are mentioned in Splashscreen.hpp right here:

Splashscreen.cpp

#include "SplashScreen.hpp"

Splashscreen::Splashscreen() {}
Splashscreen::~Splashscreen() {}

void Splashscreen::Init() {}
void Splashscreen::Update(sf::RenderWindow &window, sf::Time &deltaTime) {}
void Splashscreen::Render(sf::RenderWindow &window) {}
void Splashscreen::EventTriggered(sf::RenderWindow &window, sf::Event &event) {}

I hope someone can help me and forgive me, if this question was already to many times. But it is hard to change your "mind of programming" when you change from Java to C++. But I already like C++ better :) It is challenging and I like that a lot.

[EDIT]:

I only changed the following:

class Splashscreen : public Screen {
public:
   Splashscreen();
   ~Splashscreen();

   void Init() const;
   void Update(sf::RenderWindow &window, sf::Time &deltaTime) const;
   void Render(sf::RenderWindow &window) const;
   void EventTriggered(sf::RenderWindow &window, sf::Event &event) const;

private:
   sf::Sprite *_splashSprite;
};

The others are still the same.


Solution

  • All your pure virtual functions in Screen are defined as const . This trailing const is not only an indication that the function will not modifiy the object, but it is entirely part of the signature.

    Unfortunately, the functions with the same name in Screesplash are not defined as const. So these functions are not an override of your pure virtuals, but additional functions. This means that your pure virtual functions are still not overriden and your Screensplash is hence still an abstract class that can't be instantiated.

    To solve your issue, just add the trailing const keyword behind your functions.

    To avoid similar issues in the future, take the habit of using the override keyword to tell the compiler your intention. If by accident you have a mismatch in the signature, the compiler will immediately tell you that your function was not an override as you thought.

    class Splashscreen : public Screen {
    public:
       ...
       void Init() const override;
       void Update(sf::RenderWindow &window, sf::Time &deltaTime) const override;
       void Render(sf::RenderWindow &window) const override;
       void EventTriggered(sf::RenderWindow &window, sf::Event &event) const override;
       ...
    };