//: C10:ShapeFactory1.cpp
// Z knihy "Myslíme v jazyce C++, část 2" od Bruce Eckela a Chucka Allisona.
// (c) 1995-2004 MindView, Inc. Všechna práva vyhrazena.
// Přečtěte si podmínky používání zdrojových kódů umístěné v souboru 
// 'Licence.txt' dodávaném spolu s balíčkem kódu dostupným na www.MindView.net.
#include <iostream>
#include <stdexcept>
#include <cstddef>
#include <string>
#include <vector>
#include "../purge.h"
using namespace std;

class Tvar {
public:
  virtual void vykreslit() = 0;
  virtual void smazat() = 0;
  virtual ~Tvar() {}
  class ChybneVytvoreniTvaru : public logic_error {
  public:
    ChybneVytvoreniTvaru(string typ)
    : logic_error("Nelze vytvořit typ " + typ) {}
  };
  static Tvar* tovarna(const string& typ)
    throw(ChybneVytvoreniTvaru);
};

class Kruh : public Tvar {
  Kruh() {} // Soukromý konstruktor
  friend class Tvar;
public:
  void vykreslit() { cout << "Kruh::vykreslit" << endl; }
  void smazat() { cout << "Kruh::smazat" << endl; }
  ~Kruh() { cout << "Kruh::~Kruh" << endl; }
};

class Ctverec : public Tvar {
  Ctverec() {}
  friend class Tvar;
public:
  void vykreslit() { cout << "Ctverec::vykreslit" << endl; }
  void smazat() { cout << "Ctverec::smazat" << endl; }
  ~Ctverec() { cout << "Ctverec::~Ctverec" << endl; }
};

Tvar* Tvar::tovarna(const string& typ)
  throw(Tvar::ChybneVytvoreniTvaru) {
  if(typ == "Kruh") return new Kruh;
  if(typ == "Ctverec") return new Ctverec;
  throw ChybneVytvoreniTvaru(typ);
}

char* sl[] = { "Kruh", "Ctverec", "Ctverec",
  "Kruh", "Kruh", "Kruh", "Ctverec" };

int main() {
  vector<Tvar*> tvary;
  try {
    for(size_t i = 0; i < sizeof sl / sizeof sl[0]; i++)
      tvary.push_back(Tvar::tovarna(sl[i]));
  } catch(Tvar::ChybneVytvoreniTvaru e) {
    cout << e.what() << endl;
    purge(tvary);
    return EXIT_FAILURE;
  }
  for(size_t i = 0; i < tvary.size(); i++) {
    tvary[i]->vykreslit();
    tvary[i]->smazat();
  }
  purge(tvary);
} ///:~
