C ++:使用抽象类中的指针来访问派生类的方法;派生类apears也是抽象的

时间:2016-06-25 20:14:28

标签: c++ polymorphism abstract virtual-functions derived

我现在已经花了2个小时(主要是在这个网站上)了解我在用C ++编写代码时遇到的问题。我有一个抽象的基类,如下所示:

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;
};

接下来我声明了一个派生自基类的类:

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;
};

最后我想创建一个新的Splashscreen对象并将地址分配给基类的指针:

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

正如我之前提到的,我已经看到了这个问题,并找到了大量的解决方案,并提出了我现在所拥有的。但我仍然在行中出现错误

Screen* ptrScreen = new Splashscreen;

编译时说:

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

我只是不明白这一点,因为我已经定义了Splashscreen.hpp中提到的所有声明的方法:

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) {}

我希望有人可以帮助我并原谅我,如果这个问题已经很多次了。但是当你从Java改为C ++时,很难改变你的“编程思想”。但我已经更喜欢C ++了:)这很有挑战性,我非常喜欢它。

[编辑]:

我只更改了以下内容:

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;
};

其他人仍然是一样的。

2 个答案:

答案 0 :(得分:2)

来自Screen

virtual void Init() const = 0;

来自Splashscreen

void Init();

其中一个是const,另一个不是。您应该从const移除Screen或将其添加到Splashscreen,无论哪个有意义。

答案 1 :(得分:1)

Screen中的所有纯虚函数都定义为const。这个尾随const不仅表示该函数不会修改该对象,而且它完全是签名的一部分。

不幸的是,Screesplash中具有相同名称的功能未定义为const。因此,这些函数不是对纯虚拟的重写,而是其他功能。这意味着您的纯虚函数仍未被覆盖,因此您的Screensplash仍然是一个无法实例化的抽象类。

要解决您的问题,只需在功能后添加尾随的const关键字即可。

为避免将来出现类似问题,请习惯使用override关键字告诉编译器您的意图。如果意外的是签名不匹配,编译器会立即告诉您,您的功能不是您想象的覆盖。

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;
   ...
};