학규님께서 예전에 게제동에 쓰신
"RTTI 와 객체의 타입체크"라는 글을 읽고 실제 구현은 어떻게 하는
것일까 궁금해 하던 차, 마침 이곳을 알게되어 질문을 올립니다. 글 마지막 부분쯤에 '일반적 부분이
세부적 특징적 부분을 불러서는 안된다. 이때 도움을 줄 수 있는 것이 RTTI 와 가상함수이다.' 라고
말씀하신것을 힌트삼아 나름대로 고민도 하고 관련 자료들도 뒤져보고 했으나 명쾌하게 답이 나오지는
않더군요.
좀 다른 예이긴 하지만 RTTI를 활용한 예로 More Effective C++ 의 Item 31 같은 경우엔 오히려 RTTI 를
이용함으로써 if-then-else 코드가 들어가는 지경-_-에 이르게 되는것도 보았는지라.. 솔직히 RTTI 를
어떻게 활용해야되는지를 모르는 입장에서는 도무지 감이 잡히지를 않습니다.
당시에 생각하셨던 구체적인 구현(..은 글로 남아있지 않더군요. 사라진것인지 제가 못 찾은것인지는
모르겠지만 ^^)정도로 자세히까지는 아니더라도 추천할만한 읽을거리, 혹은 힌트가 될 만한 말 한마디
라도 부탁드리겠습니다.
이만.
switch-case 형태로 만들어놓으면, 새로운 오브젝트의 종류가 추가될 때마다 그쪽 문장도 계속 손봐주어야 하기때문에 귀찮아지는 것을 막기 위해서 factory 를 만드는 것이고, RTTI 가 도움이 되는 경우는 factory 중에서도 prototype 을 이용한 factory 생성방식입니다. prototype 방식은 간단히 설명하자면, 생성을 할 오브젝트들을 사전에 등록해놓고, 나중에 factory 에 오브젝트 생성요청이 들어오면 사전에 등록된 prototype 오브젝트가 Clone 을 하는 식으로 새로운 오브젝트를 만들어내는 것입니다. 이에 대한 자세한 예제는 Noel Llopsis 의 C++ for game programmer 라는 책에서 보실 수 있습니다. 이때 Prototype 의 id 를 자동으로 만들기 위해서 RTTI 를 사용할 수 있지요. 꼭 써야만 하는 것은 아닙니다.
그리고 RTTI 가 쓰이게 되는 경우중 가장 흔한 경우는 dynamic_cast 를 쓰는 경우입니다. 오브젝트들을 계층적으로 만드는 것은 중요한 일이긴 하지만 능사는 아닙니다. 예를 들어서 윈도우 시스템을 C++ 을 써서 만든다고 할때, 흔히 CWindow 같은 것을 만들고, CControl, CButton, CFramewindow 같은 세부 클래스들을 CWindow 로부터 상속받게 디자인하곤 합니다. 그런데 CWindow 에는 없지만, CButton 에서만 특별하게 쓰일 메소드 (예를 들면 GetPushedStatus() ) 를 만들게 된다면 어떻게 될까요? 이것을 CButton 상에 정의해 놓으면 CWindow * 로 받은 상태에서는 직접 GetPushedStatus 같은 메소드를 호출할 수가 없고, 그렇다고 CWindow 상에 정의해놓으면 계속 CWindow 쪽이 커져버리게 됩니다. 그럴 때 흔히 CWindow *로 받은 포인터를 CButton * 으로 강제 캐스팅해서 쓰곤 하는데, 만약 정말 CButton 이 아닌 다른 오브젝트의 포인터를 CButton * 으로 캐스팅할 경우 이게 틀린 것인지, 맞은 것인지 보장할 수가 없습니다. 이럴 때 dynamic_cast 를 사용하면, 만약 올바르지 않은 캐스팅을 한 경우 캐스팅의 결과값이 NULL 이 되어버리기 때문에 안전을 기할 수가 있는 것입니다.
짧은 답글에서 몇시간동안 설명해도 모자랄 복잡한 주제를 다루느라고 설명이 잘 되었는지 모르겠네요. 그럼..