#include <iostream>

class BaseObject
{
private:
  virtual void v_load() = 0;

public:
  void load() { v_load(); }
};

template<typename Derived>
class Object : public BaseObject
{
private:
  virtual void v_load() { static_cast<Derived&>(*this).load(); }
};

class Pawn : public Object<Pawn>
{
public:
  void load() { std::cout << "Pawn::load()" << std::endl; }
};

class BlackPawn : public Pawn
{
private:
  virtual void v_load() {
    std::cout << "BlackPawn::v_load()" << std::endl;
    std::cout << "- "; Pawn::load();
  }

public:
  void load() {
    std::cout << "BlackPawn::load()" << std::endl;
    std::cout << "- "; Pawn::load();
  }
};

class BigBlackPawn : public BlackPawn
{
private:
  virtual void v_load() {
    std::cout << "BigBlackPawn::v_load()" << std::endl;
    std::cout << "- "; BlackPawn::load();
  }

public:
  void load() {
    std::cout << "BigBlackPawn::load()" << std::endl;
    std::cout << "- "; BlackPawn::load();
  }
};

template<typename T>
void load(T& x)
{
  x.load();
}


void vload(BaseObject& x)
{
  x.load();
}

int main()
{
  Pawn p;
  BlackPawn bp;
  BigBlackPawn bbp;

  load(p);
  load(bp);
  load(bbp);
  std::cout << std::endl;
  vload(p);
  vload(bp);
  vload(bbp);
}