【问题标题】:Weird polymorphism behavior with multiple inheritance in C++?C ++中具有多重继承的奇怪多态行为?
【发布时间】:2012-10-04 17:35:35
【问题描述】:

所以,我正在使用 SDL 编写一个小型 Pong 游戏克隆,并且我有以下设置。

有一个通用游戏类SlimGame 继承自 FSM 类和事件处理程序类:

// DEFINITION
class SlimGame : public SlimFSM, public SlimEventHandler {
protected:
  bool    running;        // indicates if the game is running

public:
  bool isRunning() { return this->running; }
  void setRunning(bool r) { this->running = r; }

  void run();                         // encapsulates the game loop
};

// IMPLEMENTATION
void SlimGame::run() {
  SDL_Event event;

  this->setRunning(true);

  while(this->isRunning()) {
      while(SDL_PollEvent(&event)) {
          this->handleEvent(&event);
          std::cout << "MAIN LOOP Running: " << this->isRunning(); << endl;
      }

      // ...
  }
}

FSM 类与怪异行为无关,但事件处理程序类如下所示:

// DEFINITION
class SlimEventHandler {
public:
  SlimEventHandler() { }
  virtual ~SlimEventHandler() { }

  void handleEvent(SDL_Event *event);

  virtual void onExit();
};

// IMPLEMENTATION
void SlimEventHandler::handleEvent(SDL_Event *event) {
  switch(event->type) {
    case SDL_QUIT:
      this->onExit();
      break;
  }
}

void SlimEventHandler::onExit() {
  std::cout << "PARENT onExit!" << std::endl;
}

然后我的PongGame 类本身继承自SlimGame(因此间接继承自SlimFSMSlimEventHandler):

// DEFINITION
class PongGame : public SlimGame {
public:
  PongGame();
  ~PongGame();

  void onExit();
};

// IMPLEMENTATION
void PongGame::onExit() {
  this->setRunning(false);

  std::cout << "CHILD onExit!" << std::endl;
}

因此,通过这种设置,我可以像这样运行我的游戏,并且它可以很好地启动:

int main(int argc, char **argv) {
  PongGame game;

  // setup

  game.run();

  // tear down

  return 0;
}

但是,事件处理并没有按应有的方式工作。如果我单击窗口关闭按钮,则会触发 SDL_QUIT 事件并调用方法 handleEvent。这很好,但是方法本身调用了自己的onExit,而不是PongGame类的继承方法,所以我看到了:

PARENT onExit!

在控制台而不是

CHILD onExit!

不应该调用PongGame中的派生方法,而不是SlimEventHandler中的虚空实现吗?

【问题讨论】:

  • 我在一些类中存根来编译你的代码,我确实看到“CHILD onExit”,所以问题似乎出在其他地方。
  • 有趣。这可能是在库中拆分代码的问题吗?我正在使用 Mac OSX,除了 PongGame 类之外的所有内容都在静态库中......
  • 这应该没什么区别。
  • 我将run 方法移到PongGame 类中,现在它可以工作了,这很好,但不是我想要的抽象级别......非常非常奇怪!
  • 尝试使 SlimEventHandler::onExit() 成为纯虚拟的。这可能会导致编译错误,从而使问题更加明显。

标签: c++ polymorphism sdl multiple-inheritance


【解决方案1】:

您应该将您的 run() 方法声明为虚拟,以强制将您的对象指针解释为 PongGame 对象,因为目前它不是。一些编译器也可能会警告您重写 run()。在这种情况下,run() 的 PongGame 实现可以是一个简单的代码重复,大部分时间是无害的。

void PongGame::run() {
    SlimGame::run();
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-11-08
    • 1970-01-01
    • 2015-03-02
    • 2018-06-04
    • 1970-01-01
    • 2015-10-26
    • 2015-07-30
    相关资源
    最近更新 更多