Search code examples
c++oopinheritancegame-enginegame-development

Virtual methods and overriding


What am I doing?

I'm trying to do some basic inheritance for the game I'm working on. The idea is to have a base Entity class that the Player will inherit from. The Entity class has a virtual update or think method that each child will override to fit it's needs.

This is how the engine handles the update loop:

void Engine::update() {
  for (Entity entity : entities) {
    entity.update(deltaTime);
  }
}

The code:

Entity.hpp

#pragma once

#include "Position.hpp"
#include "AssetManager.hpp"
#include "Logger.hpp"

#define SPATIAL 1
#define VISUAL 1 << 1

class Entity {
public:
  Entity(Position *position, const char *visualPath);

  int flags;
  const char *visualPath;
  Position position;

  virtual void update(float deltaTime);
};

Entity.cpp

#include "Entity.hpp"

Entity::Entity(Position *position, const char *visualPath) {
  flags = 0;

  if (position) {
    flags |= SPATIAL;
    this->position = *position;
  }

  if (visualPath) {
    flags |= VISUAL;
    this->visualPath = visualPath;
  }
}

void Entity::update(float deltaTime){
  Logger::log("No update method");
};

Player.hpp

#pragma once

#include "../Entity.hpp"
#include "../Logger.hpp"

class Player : public Entity {
public:
  Player();

  void update(float deltaTime) override;
};

Player.cpp

#include "Player.hpp"

Player::Player() : Entity(new Position(0, 0), "assets/player.png") {}

void Player::update(float deltaTime) {
  this->position.x += 10;
  Logger::log("Player says hi");
}

What's the issue?

Even tho I have overridden the update method on the Entity within Player, Player still prints "No update method". It seems the override didn't do anything.


Solution

  • Change this:

    void Engine::update() {
      for (Entity entity : entities) {
        entity.update(deltaTime);
      }
    }
    

    To this:

    void Engine::update() {
      for (Entity& entity : entities) {
        entity.update(deltaTime);
      }
    }
    

    In the original implementation, your for loop makes a copy of the item in entities. You probably didn't want that, but more importantly, entity is just a copy of the base class, so the derived class information is lost. Pass by reference to avoid this issue and other bugs.