/* Voorbeeldcode behorende bij het college "Programmeertechnieken",
 * LIACS, Universiteit Leiden.
 */

#include <iostream>
#include <vector>

/* Basisklasse met een virtuele methode */
class Figuur
{
  public:
    virtual void zetOpScherm() const
    {
      std::cout << "Figuur!" << std::endl;
    }

    /* Bij een object met virtuele methode is een virtual destructor
     * met standaardimplementatie aan te raden.
     */
    virtual ~Figuur(void)
    { }
};

/* Subklassen die de methode "overriden" */
class Rechthoek : public Figuur
{
  public:
    virtual void zetOpScherm() const
    {
      std::cout << "Rechthoek!" << std::endl;
    }
};

class Vierkant : public Rechthoek
{
  public:
    virtual void zetOpScherm() const
    {
      std::cout << "Vierkant!" << std::endl;
    }
};

class Cirkel : public Figuur
{
  public:
    virtual void zetOpScherm() const
    {
      std::cout << "Cirkel!" << std::endl;
    }
};

static void test(void)
{
  Figuur *f1 = new Rechthoek();
  Figuur *f2 = new Vierkant();
  Figuur *f3 = new Cirkel();

  /* Gegeven een Figuur*, roept toch de juiste methode aan door middel van
   * "dynamic" of "late" binding.
   */
  f1->zetOpScherm();
  f2->zetOpScherm();
  f3->zetOpScherm();

  delete f1;
  delete f2;
  delete f3;
}

static void container_voorbeeld(void)
{
  std::vector<Figuur *> figuren;

  figuren.push_back(new Rechthoek());
  figuren.push_back(new Vierkant());
  figuren.push_back(new Cirkel());

  for (std::vector<Figuur*>::const_iterator it = figuren.begin();
       it != figuren.end(); ++it)
    (*it)->zetOpScherm();

  for (std::vector<Figuur*>::const_iterator it = figuren.begin();
       it != figuren.end(); ++it)
    delete (*it);
  figuren.clear();
}

static void container_voorbeeld_cxx11(void)
{
  /* Voorbeeld met C++11 features: initializer lists en
   * range-based for loop.
   */
  std::vector<Figuur *> figuren =
    { new Rechthoek(), new Vierkant(), new Cirkel() };

  for (const auto *f : figuren)
    f->zetOpScherm();

  for (std::vector<Figuur*>::const_iterator it = figuren.begin();
       it != figuren.end(); ++it)
    delete (*it);
  figuren.clear();
}

int main (void)
{
  test();
  container_voorbeeld();
  container_voorbeeld_cxx11();

  return 0;
}