-
클래스 맴버함수의 함수 포인터Computer Language/C 2007. 8. 24. 16:41728x90
일반적으로 함수 포인터는 void* 로 캐스팅되지 않는다.
- 이는 type 이나 value 보다는 name 에 instantiation 되기 때문이다.
일반적으로 맴버 함수 포인터는 일반 함수 포인터와 다르다.
- 일반적으로 콜링컨벤션은 __cdecl, __stdcall, __fastcall 이 있는것으로 알려져 있으나 하나가 더 존재한다. 그것은 바로 __thiscall
- 맴버 함수 포인터는 특이하게 스코프(::*) 가 들어가 있다. (__thiscall 과 관련있음)
- 따라서 선언할때 아주 눈게 거슬리게 선언이 된다. (그래서 보통 typedef 로 짧게 만들어 놓고 씀)
문제는 다중 상속일때 발생한다.
- 단일 상속을 하게 되면 상속받은 클래스의 엔트리 포인트를 상속한 클래스의 엔트리로 변경하는 야매로 맴버함수 포인터를 사용할 수 있다.
class A { void a(); }; class B : public A { void b(); }; // 여기서 B::a() 의 포인터를 선언하면 모양새는 B::a() 가 되지만 실제 값은 B 대신 A가 들어가 있다. 자연히 A::a()가 호출됨
- 문제는 다중상속인데 이를 해결하기 위해 함수 포인터에 offset 이용함
- offset 때문에 맴버함수포인터의 size 가 기존 포인트size 보다 커지게 됨.
- VC++일 경우 포인터 크기는 아래와 같음
int : 4 byte
data pointer : 4
code pointer : 4
단일상속맴버 pointer : 4
다중상속맴버 pointer : 8
Virtual 맴버 pointer : 12
Unknown pointer : 16일반적으로 MFC에 메시지맵(맴버가상함수포인터상속한뒤캐스팅을 활용한 대표적인예) 에서는 어떤 야매를 썼나
union MessageMapFunctions
{
AFX_PMSG pfn; // generic member function pointer
// specific type safe variants for WM_COMMAND and WM_NOTIFY messages
void (AFX_MSG_CALL CCmdTarget::*pfn_COMMAND)();
BOOL (AFX_MSG_CALL CCmdTarget::*pfn_bCOMMAND)();
void (AFX_MSG_CALL CCmdTarget::*pfn_COMMAND_RANGE)(UINT);
BOOL (AFX_MSG_CALL CCmdTarget::*pfn_COMMAND_EX)(UINT);
void (AFX_MSG_CALL CCmdTarget::*pfn_UPDATE_COMMAND_UI)(CCmdUI*);
void (AFX_MSG_CALL CCmdTarget::*pfn_UPDATE_COMMAND_UI_RANGE)(CCmdUI*, UINT);
void (AFX_MSG_CALL CCmdTarget::*pfn_OTHER)(void*);
BOOL (AFX_MSG_CALL CCmdTarget::*pfn_OTHER_EX)(void*);
- 위와 같은 엄청난 분량의(나올수 있는 가능성이 있는 모든 함수) 포인터를 union 으로 묶었다.
'Computer Language > C' 카테고리의 다른 글
포인터로 함수 호출하기 (0) 2007.08.24 함수포인터 타입 (0) 2007.08.24 [펌] 함수포인터 정의 (0) 2007.08.24 [펌] 포인터 캐스팅을 이용한 실제 인터페이스 변경 (0) 2007.08.24 구조체의 패딩에 대해서... (2) 2007.03.26