RTTI는 Run-Time Type Information의 약자로써, 실행시간에 객체의 타입 정보를 얻게 하는 C++의 확장? 정도 이다.
자바나 C#의 경우에는 리플렉션의 축소판 정도라고 생각하면 되겠다.
우선은 RTTI를 위하여 구현해야 하는 기능을 보자.
- 실행 시에 알려지지 않은 클래스의 이름과 크기를 얻을 수 있어야 한다.
- 실행 시에 알려지지 않은 클래스를 동적으로 생성할 수 있어야 한다.
우선 실행 시에 클래스의 이름을 얻는 방법부터 보자.
이를 위해서는 딱 두가지의 처리만 해주면 된다.
1. 자신의 클래스의 이름을 저장하는 정적변수를 만든다.
2. 그 이름을 리턴하는 GetClassName()을 오버라이드(override)한다.
소스로 보는 것이 더 확실할 것이다.
class CObject {
public:
// 자신의 클래스이름을 반환하는 메서드를 만든다.
virtual char* GetClassName() const { return NULL; }
};
class CSomeObject : public CObject {
public:
// 자신의 클래스 이름을 반환하는 메서드를 오버라이드한다.
virtual char* GetClassName() const { return lpszClassName; }
// 자신의 클래스의 이름을 저장하는 정적변수를 만든다.
static char lpszClassName[];
};
char CSomeObject::lpszClassName[] = "CSomeObject";
void main() {
// 사용하는 방법.
CObject *p;
p = new CSomeObject;
cout << p->GetClassName(); // 동적으로 만들어진
// 클래스의 이름을 알 수 있다!!
delete p;
}
실행결과는 다음과 같을 것이다.
CSomeObject
이것을 매크로로 정의하여 편하게 사용하여 보자.
그 매크로는 바로 두구두구두구두구!!!!
DECLARE_CLASSNAME(s)
IMPLEMENT_CLASSNAME(s)
위의 두 매크로들이다.
선언은 아래와 같이 되어있다.
#define DECLARE_CLASSNAME(s) static char lpszClassName[]
#define IMPLEMENT_CLASSNAME(s) char s##::lpszClassName=(#s)
간단하게 사용하는 예제를 적어본다.
(위의 예제와 똑같은 것이므로 주석은 안 달았다.)
class CObject {
public:
virtual char* GetClassName() const { return NULL; }
};
class CSomeObject : public CObject {
public:
DECLARE_CLASSNAME(CSomeObject);
virtual char* GetClassName() const { return lpszClassName; }
};
IMPLEMENT_CLASSNAME(s);
void main() {
CObject *p;
p = new CSomeObject;
cout << p->GetClassName();
delete p;
}
이제 실행 시에 클래스의 이름을 알아내는 방법은 알았다.
책에서는 저렇게 하였으나, 개인적인 생각으로는
DECLARE_CLASSNAME(s) 매크로를
#define DECLARE_CLASSNAME(s) static char lpszClassName[];
virtual char* GetClassName() const { return lpszClassName; }
으로 하는 것이 나을 꺼 같다.
-------------------------------------------------------------------------------
이제 동적 생성을 지원하기 위한 조건을 알아보도록 하겠습니다.
우선 동적 생성을 지원하는 클래스를 만들기 위해서
코드 자동 생성기가 해야 하는 작업을 구체적으로 살펴보면,
1. 객체의 클래스 이름을 알 수 있어야 되며,
2. 객체의 크기를 알 수 있어야 되며,
3. 클래스를 동적으로 생성하기 위한 함수를 갖어야 한다.
위의 작업이 가능하도록 구조체를 만들어 봅니다.
struct CRuntimeClass {
char m_lpszClassName[21]; // 객체의 클래스 이름
int m_nObjectSize; // 객체의 크기
CObject* (*pfnCreateObject)(); // 실제 객체를 생성하기 위한 함수 포인터
CObject* CreateObject; // 객체를 생성하기 위한 함수(인터페이스)
};
// 단순히 pfnObject 함수포인터를 랩핑(wrapping)한다.
CObject* CRuntimeClass::CreateObject() { return (*pfnObject)(); }
'MFC' 카테고리의 다른 글
MFC의 구조 (1) | 2008.09.02 |
---|---|
DEBUG_NEW 간단한 이해 윈도우 프로그래밍 (0) | 2008.09.02 |
MFC 객체간 통신 방법 (0) | 2008.09.02 |
MFC 프로그램의 흐름 살펴보기 - 인터널 (1) | 2008.09.01 |
AfxEndDeferRegisterClass, AfxWndProc - MFC 살펴보기 (0) | 2008.09.01 |
클래스 멤버 함수를 윈도우 프로시져로 등록하기 [3/3] (0) | 2008.09.01 |
클래스 맴버함수를 콜백함수로 사용하기 [2/3] (1) | 2008.09.01 |