'클래스'에 해당되는 글 2건

  1. 2006.11.20 CRuntimeClass
  2. 2006.11.20 동적 생성 지원 클래스 만들기


CRuntimeClass

Development/C / C++ 2006. 11. 20. 17:04
출처 : 검색 부분 발췌

헤더를 보면 다음과 같은 매크로가 있다.

   DECLARE_DYNCREATE(CMainFrame)

이것은 무엇인가?... 궁금하지 않은가?.. 바로 이것은.. RunTimeClass라는 구조체를 사용하겠다고 선언하는 것이다. 자세한 것은 솔직이 본인도 잘 모르지만.. 런타임 구조체라는게 어떤 것이라는 건 한번 되짚고 넘어가 볼 필요가 있다.

다음은 런타임 클래스의 정의를 설명해 놓은 원문이다.

CRuntimeClass does not have a base class.
Each class derived from CObject is associated with a CRuntimeClass structure that you can use to obtain information about an object or its base class at run time.

// 런타임 클래스 구조체는 기초 클래스가 없다.
CObject에서 파생된 각각의 클래스는 런타임 클래스와 연결되어 당신은 프로그램 실행시 (이하 실시간) 그때그때마다 오브젝트나 그것의 베이스 클래스에 대한 정보를 얻어낼 수 있다. //

이상이다. 이건 무슨 뜻일까?.. 프로그램이 실행될 때.. 탑다운 방식에서는 무조건 위에서 아래로 내려오면서 실행된다. 하지만 MFC는 적어도 그렇지 않다.
프로그램이 시작되면서 이벤트를 발생시키고 각각 그 이벤트의 정보가 다르다. 실시간마다.. 서로 다른 정보를 이쪽 저쪽으로 왔다갔다 하면서.. 설정한다는 말이다. 바로.. 프로그램이 긴박하게 돌아갈 때.. 우리가 발생시키는 메시지(이것 말고도 사실 실시간 중에는 많은 정보들이 왔다갔다 할 것이다. 하드웨어쪽으로 몰라서 뭐라고 자세히 설명드릴 수 없는 데 대해 사죄의 말씀을..--;)의 정보를 숨가쁘게 받아내야 할 것이고.. 런타임 에러에 걸리는지 안걸리는지... 실시간 에러처리까지 헤줘야 하는 것이다. 하드웨어에서 이처럼 그때그때 실시간 처리를 해주지 못한다면 그 프로그램의 실행은 불 보듯 뻔한거 아니겠는가.. 불.가.능..이겠다..

바로 런타임 구조체는 그런 면에서 유용하게 쓰인다. 나중에 Multi Document Interface를 공부하게 될 즈음.. View와 Document 그리고 Frame을 App에서 각각 실시간으로 어떻게 연결해주는지... 보게 될 것이다. 사실상... 런타임까지는 본인도 자세히 알지는 못하는 바다. MDI 만들 때 가끔씩 써보는 것 외엔..

이제 무슨 말인지 이해하셨을 것이다. 어쨌든.. 저 위의 한 줄.. 은 이러한 런타임 구조를 쓰겠다고 선언하는 것이다.


:

동적 생성 지원 클래스 만들기

Development/C / C++ 2006. 11. 20. 16:45
//RTTI(run time type information) example
#include
#include



#define RUNTIME_CLASS(class_name) (&class_name::class##class_name)



class CObject;

//{{struct CRuntimeClass------------------------------------------------
struct CRuntimeClass {
char m_lpszClassName[21];
int m_nObjectSize;
CObject* (*pfnCreateObject)();

CObject* CreateObject();
};//struct CRunTimeClass

CObject* CRuntimeClass::CreateObject() {
return (*pfnCreateObject)();//함수 포인터를 이용하여
//간접적으로 함수를 호출한다.
}//CRuntimeClass::CreateObject()
//}}struct CRuntimeClass------------------------------------------------

//{{class CObject-------------------------------------------------------
class CObject {
//CObject는 순수 가상함수를 포함하지 않으므로
//추상 클래스가 아니다. 하지만, 생성자가 protected로 설정되었으므로,
//CObject객체를 생성할 수 없다.
public:
virtual CRuntimeClass* GetRuntimeClass() const { return NULL; }
//파생 클래스에서 반드시 구현할 필요가 없으므로
//순수가상함수가 아니다.
static CRuntimeClass classCObject;
//DECLARE_DYNAMIC(CObject)
virtual ~CObject(){}
protected:
CObject(){ printf("CObject constructor\n"); }
};//class CObject

CRuntimeClass CObject::classCObject={//IMPLEMENT_DYNAMIC(CObject)
"CObject",sizeof(CObject),NULL
};
//}}class CObject-------------------------------------------------------

//{{class CAlpha--------------------------------------------------------
class CAlpha : public CObject {
public:
virtual CRuntimeClass* GetRuntimeClass() const {
return &classCAlpha;
}
static CRuntimeClass classCAlpha;
//DECLARE_DYNAMIC(CAlpha)
static CObject* CreateObject();
//DECLARE_DYNCREATE(CAlpha)
protected:
CAlpha() { printf("CAlpha constructor\n"); }
};//class CAlpha

CRuntimeClass CAlpha::classCAlpha = {//IMPLEMENT_DYNAMIC(CAlpha)
"CAlpha", sizeof(CAlpha), CAlpha::CreateObject
};

CObject* CAlpha::CreateObject() {//IMPLEMENT_DYNCREATE(CAlpha)
return new CAlpha;
}
//}}class CAlpha--------------------------------------------------------

//{{class CBeta---------------------------------------------------------
class CBeta : public CObject {
public:
virtual CRuntimeClass* GetRuntimeClass() const {
return &classCBeta;
}
static CRuntimeClass classCBeta;
//DECLARE_DYNAMIC(CBeta)
static CObject* CreateObject();
//DECLARE_DYNCREATE(CBeta)
protected:
CBeta() { printf("CBeta constructor\n"); }
};//class CBeta

CRuntimeClass CBeta::classCBeta = {//IMPLEMENT_DYNAMIC(CBeta)
"CBeta", sizeof(CBeta), CBeta::CreateObject
};

CObject* CBeta::CreateObject() {//IMPLEMENT_DYNCREATE(CBeta)
return new CBeta;
}
//}}class CBeta---------------------------------------------------------

void main() {
//Create CAlpha
CRuntimeClass* pRTCAlpha=RUNTIME_CLASS(CAlpha);
CObject* pObj1;

pObj1=pRTCAlpha->CreateObject();
//struct RuntimeClass의 CreateObject()가 호출되지만
//IMPLEMENT_DYNCREATE 매크로에 의해 CAlpha의 &CreateObject()가
//대입되어 있으므로, 결국은 CAlpha의 CreateObject()가 호출되어
//동적으로 객체를 생성하게 된다.
//문제를 푸는 열쇠는 바로 '함수 포인터'이다.
printf("CAlpha class=%s\n", pObj1->GetRuntimeClass()->m_lpszClassName);

//Create CBeta
CRuntimeClass* pRTCBeta=RUNTIME_CLASS(CBeta);
CObject* pObj2;

pObj2=pRTCBeta->CreateObject();
printf("CBeta class=%s\n", pObj2->GetRuntimeClass()->m_lpszClassName);
//일관된 방법으로 클래스를 만들고 해제하는 것에 주목하라.

delete pObj1;
delete pObj2;
}//main





// 매크로를 사용한 소스



//RTTI(run time type information) example
#include
#include



//{{RTTI macros---------------------------------------------------------
#define RUNTIME_CLASS(class_name) (&class_name::class##class_name)



#define DECLARE_DYNAMIC(class_name) static\
CRuntimeClass class##class_name;



#define IMPLEMENT_DYNAMIC(class_name) CRuntimeClass\
class_name::class##class_name = {\
(#class_name),\
sizeof(class_name),\
class_name::CreateObject };



#define DECLARE_DYNCREATE(class_name) static CObject* CreateObject();



#define IMPLEMENT_DYNCREATE(class_name) CObject*\
class_name::CreateObject() {\
return new class_name; }
//}}RTTI macros---------------------------------------------------------

class CObject;//forward declaration of CObject

//{{struct CRuntimeClass------------------------------------------------
struct CRuntimeClass {
char m_lpszClassName[21];
int m_nObjectSize;
CObject* (*pfnCreateObject)();

CObject* CreateObject();
};//struct CRunTimeClass

CObject* CRuntimeClass::CreateObject() {
return (*pfnCreateObject)();//함수 포인터를 이용하여
//간접적으로 함수를 호출한다.
}//CRuntimeClass::CreateObject()
//}}struct CRuntimeClass------------------------------------------------

//{{class CObject-------------------------------------------------------
class CObject {
//CObject는 순수 가상함수를 포함하지 않으므로
//추상 클래스가 아니다. 하지만, 생성자가 protected로 설정되었으므로,
//CObject객체를 생성할 수 없다.
public:
virtual CRuntimeClass* GetRuntimeClass() const { return NULL; }
//파생 클래스에서 반드시 구현할 필요가 없으므로
//순수가상함수가 아니다.
DECLARE_DYNAMIC(CObject)
//static CRuntimeClass classCObject;
virtual ~CObject(){}
protected:
CObject(){ printf("CObject constructor\n"); }
};//class CObject

CRuntimeClass CObject::classCObject={
"CObject",sizeof(CObject),NULL
};
//}}class CObject-------------------------------------------------------

//{{class CAlpha--------------------------------------------------------
class CAlpha : public CObject {
public:
virtual CRuntimeClass* GetRuntimeClass() const {
return &classCAlpha;
}
DECLARE_DYNAMIC(CAlpha)
//static CRuntimeClass classCAlpha;
DECLARE_DYNCREATE(CAlpha)
//static CObject* CreateObject();
protected:
CAlpha() { printf("CAlpha constructor\n"); }
};//class CAlpha

IMPLEMENT_DYNAMIC(CAlpha)
//CRuntimeClass CAlpha::classCAlpha = {
// "CAlpha", sizeof(CAlpha), CAlpha::CreateObject
//};

IMPLEMENT_DYNCREATE(CAlpha)
//CObject* CAlpha::CreateObject() {
// return new CAlpha;
//}
//}}class CAlpha--------------------------------------------------------

//{{class CBeta---------------------------------------------------------
class CBeta : public CObject {
public:
virtual CRuntimeClass* GetRuntimeClass() const {
return &classCBeta;
}
DECLARE_DYNAMIC(CBeta)
//static CRuntimeClass classCBeta;
DECLARE_DYNCREATE(CBeta)
//static CObject* CreateObject();
protected:
CBeta() { printf("CBeta constructor\n"); }
};//class CBeta

IMPLEMENT_DYNAMIC(CBeta)
//CRuntimeClass CBeta::classCBeta = {
// "CBeta", sizeof(CBeta), CBeta::CreateObject
//};

IMPLEMENT_DYNCREATE(CBeta)
//CObject* CBeta::CreateObject() {
// return new CBeta;
//}
//}}class CBeta---------------------------------------------------------

void main() {
//Create CAlpha
CRuntimeClass* pRTCAlpha=RUNTIME_CLASS(CAlpha);
CObject* pObj1;

pObj1=pRTCAlpha->CreateObject();
//struct RuntimeClass의 CreateObject()가 호출되지만
//IMPLEMENT_DYNCREATE 매크로에 의해 CAlpha의 &OnCreate()가
//대입되어 있으므로, 결국은 CAlpha의 OnCreate()가 호출되어
//동적으로 객체를 생성하게 된다.
//문제를 푸는 열쇠는 바로 '함수 포인터'이다.
printf("CAlpha class=%s\n", pObj1->GetRuntimeClass()->m_lpszClassName);

//Create CBeta
CRuntimeClass* pRTCBeta=RUNTIME_CLASS(CBeta);
CObject* pObj2;

pObj2=pRTCBeta->CreateObject();
printf("CBeta class=%s\n", pObj2->GetRuntimeClass()->m_lpszClassName);
//일관된 방법으로 클래스를 만들고 해제하는 것에 주목하라.

delete pObj1;//delete pRTCAlpha는 왜 (논리적) 에러인가?
delete pObj2;
}//main

: