// dedeni.cpp : Defines the entry point for the console application.
//

#include <iostream>
using namespace std;


class CGraphBase
{
protected:
// definice spolecnych promennych
int iIndex;

public:
// definice spolecneho rozhrani
virtual double MinX(void) = 0;
virtual double MaxX(void) = 0;
virtual void Translate(double aX, double aY) = 0;
virtual void LogV(const char *aStr) = 0;
}; /* class CGraphBase */


class CPoint: public CGraphBase
{
// public kvuli prirazeni ukazatele do tgrbase – proc
static int iTotal, iLiving;
double iX, iY;

public:
CPoint(void)
{ iX = iY = 0; iTotal++; iLiving++; iIndex = iTotal; Log(" konstruktor void "); }

CPoint(double aX, double aY = 0)
{ iX = aX; iY = aY; iTotal++; iLiving++; iIndex = iTotal; Log(" konstruktor iX,iY "); }

virtual ~CPoint(void)
{ iLiving--; Log(" destruktor "); } // pouze kvuli tisku

double GetX(void)
{ return iX; }

double GetY(void)
{ return iY; }

virtual double MinX(void)
{ Log("Min X"); return iX; }

virtual double MaxX(void)
{ Log("Max iX"); return iX; }

virtual void Translate(double aX, double aY)
{ iX += aX; iY += aY; Log("Translate"); }

void Log(const char *aStr)
{ cout << " bod " << iTotal << " " << iLiving << " " << iIndex << " / " << iX << ", " << iY << aStr << endl; }

virtual void LogV(const char *aStr)
{ Log(aStr); }

friend ostream& operator<<(ostream &os, const CPoint &aPoint);
}; /* class CPoint */

ostream& operator<<(ostream &os, const CPoint &aPoint)
{
os << '[' << aPoint.iX << ", " << aPoint.iY << ']';
return os;
}



class CLine: public CGraphBase
{
static int iTotal, iLiving;
CPoint iA, iB;

public:
CLine(void)
{ iTotal++; iLiving++; iIndex = iTotal; Log(" konstruktor void "); }

CLine(double x1, double y1, double x2, double y2):iA(x1, y1), iB(x2, y2)
{ iTotal++; iLiving++; iIndex = iTotal; Log(" konstruktor int,int,int,int "); }

CLine(CPoint &aa, CPoint &bb)
{ iA = aa; iB = bb; iTotal++; iLiving++; iIndex = iTotal; Log(" konstruktor CPoint,CPoint "); }

virtual ~CLine(void)
{ iLiving--; Log(" destruktor "); }

double MinX(void)
{ Log("Min X"); return iA.GetX() < iB.GetX() ? iA.GetX() : iB.GetX(); }

double MaxX(void)
{ Log("Max X"); return iA.GetX() > iB.GetX() ? iA.GetX() : iB.GetX(); }

void Log(const char *aStr)
{ cout << " line " << iTotal << " " << iLiving << " " << iIndex << " / " << iA << ", " << iB << aStr << endl; }

virtual void LogV(const char *aStr)
{ cout << " line " << iTotal << " " << iLiving << " " << iIndex << " / " << iA << ", " << iB << aStr << endl; }

virtual void Translate(double aX, double aY)
{ iA.Translate(aX, aY); iB.Translate(aX, aY); Log("Translate"); }

friend ostream& operator<<(ostream &os, const CLine &aLine);
}; /* class CLine */

ostream& operator<<(ostream &os, const CLine &aLine)
{
os << '(' << aLine.iA << ", " << aLine.iB << ')';
return os;
}

void f(void)
{
CPoint bod, b2(2, 4);
CLine line, l2(1, 2, 3, 4), l3(bod, b2);
CLine *l4;

l4 = (CLine*) new CPoint(10, 10); // pokud pracujeme s virtual funkcemi, pak je
// dulezite, jak prvek vznikl iA ne ceme je prirazen (musi respektovat dedicnost)

#define PRVKU 6
CGraphBase *pole[PRVKU] = { &bod,&line,&b2,&l2,&l3,l4 };
int i;
double MinX = 1e32, MaxX = -1e32;

for(i = 0; i < PRVKU; i++)
{
if(pole[i]->MinX() < MinX)
MinX = pole[i]->MinX();

if(pole[i]->MaxX() > MaxX)
MaxX = pole[i]->MaxX();
}
cout << " minimum iX = " << MinX << "\n";
cout << " maximum iX = " << MaxX << "\n";

for(i = 0; i < PRVKU; i++)
pole[i]->Translate(3.5, -4);

MinX = 1e32;
MaxX = -1e32;
for(i = 0; i < PRVKU; i++)
{
if(pole[i]->MinX() < MinX)
MinX = pole[i]->MinX();

if(pole[i]->MaxX() > MaxX)
MaxX = pole[i]->MaxX();
}

cout << " minimum iX = " << MinX << "\n";
cout << " maximum iX = " << MaxX << "\n";


l4->Log(" line jako bod "); // neni virtualni iA proto si mysli, ze je to line
l4->LogV(" line jako bod virtual "); // virtualni se vola podle vzniku tj. bod

delete l4; // neni-li destructor virtual, zavola se destruktor od line, protože
// prekladac vi, ze je to line. U virtual respektuje ze to vzniklo jako bod
}

int CPoint::iLiving = 0;
int CPoint::iTotal = 0;
int CLine::iLiving = 0;
int CLine::iTotal = 0;

int main(int argc, char* argv[])
{
// char c;
f();
// cin >> c;
return 0;
}