먼저번의 CObject 클래스 부분에서 잠깐 언급한 CRuntimeClass 구조체를 이용하여 클래스를 동적으로 생성시크는 코드에 대해 말합니다.
이 방법은 여러모로 사용하기 편하고 쓰레드 클래스 생성시에도 사용가능 하지요.

COject 클래스의 매크로 DECLARE_DYNAMIC이나 DECLARE_DYNCREATE 사용시 Ructime으로 객체를 생성할 수 있다하였습니다.

이유룰 간단히 말씀드리면 DECLARE_DYNAMIC이나 DECLARE_DYNCREATE 매크로는 CObject 클래스에서 CRuntimeClass의 static 멤버를 갖게 됩니다.

이 멤버는 template Class로 정의가 되고 이 클래스의 포인터는 RUNTIME_CLASS 매크로를 사용하면 얻을 수 있습니다.

RUNTIME_CLASS는 다음처럼 정의되죠.
#define RUNTIME_CLASS(class_name) (&class_name::class##class_name)으로 정의되 있습니다.

또 CRuntimeClass 구조체는 다음의 데이터를 가지고 있구요.
struct CRuntimeClass
{
LPCSTR m_lpszClassName;
int m_nObjectSize;
UINT m_wSchema
CObject* (PASCAL* m_pfnCreateObject)( );
CObject* CreateObject( );

CRuntimeClass* (PASCAL* m_pfnGetBaseClass)( );
CRuntimeClass* m_pBaseClass;
BOOL IsDerivedFrom(const CRuntimeClass* pBaseClass) const;
};

위 멤버중 중요하게 생각하실 멤버는 m_lpszClassName, m_nObjectSize, m_pfnCreateObject, CreateObject( )가 중요합니다.
각 멤버를 보면 m_lpszClassName은 생성된 클래스 이름, m_nObjectSize는 메모리가 현재 유효한지 검사하기 위해 사용하며 m_pfnCreateObject는 CreateObject()의 함수포인터를 선언하는 곳입니다.

CreateObject 함수가 실제로 그 클래스들을 동적으로 생성시키는 부분입니다.

MFC를 예로 들면 보통 App클래스의 InitInstance 함수에서 다음처럼 되어 있는 부분을 보시기 바랍니다.
CSingleDocTemplate* pDocTemplate;
pDocTemplate = new CSingleDocTemplate(
    IDR_MAINFRAME,
    RUNTIME_CLASS(CMyDoc),
    RUNTIME_CLASS(CMainFrame),       // main SDI frame window
    RUNTIME_CLASS(CMyView));
AddDocTemplate(pDocTemplate);

위에서 CSingleDoctemplate 클래스는 SDI를 정의한 부분입니다.(이에대해서는 MSDN에 자세히 나와 있습니다.)

그리고 그 생성자에서 바로 Application에 대해 Document, MainFrame, View를 동적으로 생성시킵니다.

그런데 위 3가지 클래스의 헤더파일에 선언된 생성자를 보면 모두 protected 로 선언이 되어 있어 CMyView myView; 형태로 객체를 생성시키지 못하지요.
그리고 각 클래스들은 CRuntimeClass 멤버를 사용할 수 있게 DECLARE_DYNAMIC이나 DECLARE_DYNCREATE 매크로를 사용한 것을 볼 수 있을 것입니다.

즉 MFC에서는 위의 형태로 클래스 객체를 동적으로 생성시킬 수 있는 것입니다.
그러면 각각의 CreteObject() 함수는 어떻게 정의되어 있을까요?

view를 예로 들면
CObject* CView::CreateObject()
{
    return new CView;
}
형태로 되어 있어 여기서 메모리 로딩이 되지요. 물론 생성자도 호출이 되고...


그러면 여러분의 이해를 돕기위해 간단히 MFC식으로 C++ 코드를 사용하여 한번 코딩해보면

//Runtime 매크로 정의
#define RUN_TIME_CLASS(class_name) (&class_name::class##class_name)

//베이스 클래스 정의및 선언
class CObject;  //베이스 클래스 선언

//////////////Runtime 구조체 정의////////////////////////////////////////////
struct CRuntime  //CRuntimeClass 대신 CRuntime으로... (그리고 중요부분만 정의)
{
LPCSTR m_lpszClassName;
int m_nObjectSize;
CObject* (*m_pfnCreateObject)( );
CObject* CreateObject( );
};


////////////////베이스 클래스 정의//////////////////////////////////////////
class CObject
{
public:
    virtual CRuntime* GetRuntime()const {return NULL; } //Object의 ClassName은 없슴.

    static CRuntime classObject;    //DYNAMIC 매크로 사용시

    virtual ~CObject() {}

protected:
    CObject() { cout << "생성자 CObject!!" << endl ; }
};

//static 멤버변수 초기화
CRuntime CObject::classObject = {"CObject", sizeof(CObject), NULL};

CObject* CRuntime::CreateObject()
{
    return (*m_pfnCreateObject)(); //함수 포인터를 사용
}

////////////////View 클래스////////////////////////////////////////////////
class CView : public CObject
{
public:
    virtual CRuntime* GetRuntime* GetRuntime()const { return &classCView; }
    static CRuntime classCView;    //DYNAMIC 매크로 사용시
    static CObject* CreteObject(); //DYNCREATE 매크로 사용시

protected:
    CView() { cout << "생성자 CView!!" << endl; }
};

CRuntime CView::classCView = {"CView", sizeof(CView), CView::CreateObject};

CObject* CView::CreateObject()
{
    return new CView; //생성
}


////////////////Document Class ////////////////////////////////////////
class CDoc : public CObject
{
public:
    virtual CRuntime* GetRuntime* GetRuntime()const { return &classCDoc; }
    static CRuntime classCDoc;    //DYNAMIC 매크로 사용시
    static CObject* CreteObject(); //DYNCREATE 매크로 사용시

protected:
    CDoc() { cout << "생성자 CDoc!!" << endl; }
};

CRuntime CDoc::classCDoc = {"CDoc", sizeof(CDoc), CDoc::CreateObject};

CObject* CDoc::CreateObject()
{
    return new CDoc; //생성
}

//////////////////프로그램 메인함수 /////////////
void main()
{
    CRuntime* pView = RUN_TIME_CLASS(CView);
    CObject* pObjectView = pView->CreateObject();

    cout << "View Class Name: " <<
              pObjectView->GetRuntime()->m_lpszClassName << endl;

    CRuntime* pDoc = RUN_TIME_CLASS(CDoc);
    CObject* pObjectDoc = pDoc->CreateObject();

    cout << "Doc Class Name: " <<
             pObjectDoc->GetRuntime()->m_lpszClassName << endl;

    delete pObjectView;
    delete pObjectDoc;
}

의 형태로 MFC는 클래스를 동적으로 생성합니다.
물론 소멸은 MFC에서 하는 방법은 아니지만 여러분들이 MFC FrameWork을 직접 분석해 보시면 아실 겁니다.

+ Recent posts