// 1. prototype 디자인패턴. - 가상복사생성자
// 2. Template Method 디자인패턴( C++에서는NVI라고도불린다. )
// VC2005 에서는반환형을자기로가져도된다. 아래참고
//      virtual Shape* Clone() { return new Circle(*this); }
//      virtual Circle* Clone() { return new Circle(*this); }
class Shape
{
public:
        // 자신의 복사본을 만들어내는 가상함수-> 가상복사생성자(prototype 디자인패턴)
        virtual Shape* Clone() { return new Shape(*this); }
        // 비가상함수.. public 에가상함수를놓지말자. 
        void Draw()
        {
               // 멀티스레드를대비해서동기화객체를얻는다.
               RealDraw();    // 내부구현에서 가상함수를 호출하자.
               //cout << "Shape::Draw" << endl;
               // 동기화 객체를 반납한다.
        }
protected:
        // 모든 가상함수는 protected에 놓자.
        virtual void RealDraw()
        {
               cout << "Shape::Draw" << endl;
        }
};
class Rectangle : public Shape
{
public:
        void RealDraw()        { cout << "Rectangle::Draw" << endl; }
        virtual Rectangle* Clone() { return new Rectangle(*this); }
};
class Circle : public Shape
{
public:
        void RealDraw()        { cout << "Circle::Draw" << endl; }
        virtual Circle* Clone() { return new Circle(*this); }
};
void main()
{
        Shape* buf[1000];      // 동종의 객체(모든종류의도형)을 보관 할 수 있다.
        int count = 0;
        int cmd;
        while ( 1 )
        {
               cin >> cmd;
               if ( cmd == 4 )
               {
                       cout << "몇번째 도형을 복사할까요? >> ";
                       int k;
                       cin >> k;
                       buf[count++] = buf[k]->Clone();
               }
               if ( cmd == 1 ) buf[count++] = new Rectangle;
               if ( cmd == 2 ) buf[count++] = new Circle;
               if ( cmd == 3 ) 
               {
                       for ( int i = 0; i < count; ++i )
                              buf[i]->Draw();       // 다형성을띠게된다.
               }
        }
}