class Shape
{
public:
    virtual ~Shape() {}
};
// Rect의 생성을 5개 이하로 제약을 주고싶다면?
class Rect : public Shape
{
public:
};
class Circle : public Shape
{
public:
};
int main()
{
}
class Rect : public Shape
{
    Rect() {}       // 외부생성을 금지한다.
public:
    // 방법 1. - static 멤버 함수를 이용 객체 생성
    static Rect* Create() { return new Rect; }
};
void CreateAndDraw(Shape* (*f)())
{
    Shape* p = f();
    p->Draw();
}
int main()
{
    CreateAndDraw(&Rect::Create);
}
class Rect : public Shape
{
    Rect() {}
public:
    friend class ShapeFactory;
};
class Circle : public Shape
{
    Circle() {}
public:
    friend class ShapeFactory;
};
// 방법2. 한 곳에서 객체를 만드는것을 담당하자
class ShapeFactory
{
public:
    Shape* CreateShape(int type)
    {
        Shape* p = 0;
        switch(type)
        {
            case 1: p = new Rect; break;
            case 2: p = new Circle; break;
        }
        return p;
    }
};
int main()
{
    ShapeFactory factory;
    Shape* p = factory.CreateShape(1);
}
class Shape
{
public:
    virtual ~Shape() {}
    // 방법 3. 복사해서 만드는 방법
    virtual Shape* Clone() = 0;
};
class Rect : public Shape
{
    Rect() {}
public:
    virtual Shape* Clone() { return new Rect(*this); };
};
int main()
{
    Shape* p = new Rect;
    Shape* p2 = p->Clone();
}