티스토리 뷰

일반적으로 다양한 형태의 포인터를 담기 위해 사용하는 방법 중에 주로 사용되는 방식은 두 방식입니다.

첫번째로 void *로 담는 방법과, 두번째로 상위 클래스를 두고 해당 클래스를 상속 받고, 상위 클래스 포인터로 관리하는 방법이 있죠. 

void*로 담는 방식의 단점은, 원본 포인터형이 아닌 다른 포인터형으로 캐스팅 하는 실수를 방지하기 어려운 문제가 있습니다.

상위 클래스 포인터로 다루는 방식은, 상속이 가능한 자료구조에만 사용 가능하다는 점과, 불필요한 상속을 유발하는 경우도 발생한다는 문제가 있습니다. 


주로 포인터 변환은 콜백에서 많이 이루어지는데요, 제대로된 변환을 시도하느냐 그렇지 않느냐에 따라 변환 성공 여부를 반환해준다면 좋겠죠? 

이에 대한 대안으로 AnyPtr이라는 것이 있습니다. 
포인터 타입을 관리해주다가 잘못된 포인터 타입으로 대입을 시도하면 NULL을 반환해주는 멋진 클래스죠. 

사용 예를 보실까요?
//UnitTest++ 용 단위 테스트 코드 입니다.
TEST(ANYPTR_TEST) 
{
	// Variables of different types.
	int   intVar   = 10;
	float floatVar = 20.5f;

	// CAnyPtrs which point to the variables of different types.
	any_ptr ptr1 = &intVar;
	any_ptr ptr2 = &floatVar;
// Raw pointers which are assigned from the CAnyPtr. const int *pInt = ptr1; // Assigning non-const to const of the same type is valid, but not vice versa. float *pFloat = ptr2; // The raw pointers will be valid because CAnyPtrs of their corresponding type are assigned to them. // The raw pointers should point to the correct variables. CHECK( pInt == &intVar ); CHECK( pFloat == &floatVar ); // Swap the CAnyPtrs. std::swap( ptr1, ptr2 ); // ptr1 will now point to floatVar; ptr2 will now point to intVar. // Reassign the raw pointers. pInt = ptr1; pFloat = ptr2; // The raw pointers will be null because the CAnyPtrs assigned to them are not of their corresponding type. // The raw pointers should be null. CHECK( pInt == 0 ); CHECK( pFloat == 0 ); }
A Type-safe Generic Pointer 

위 링크를 따라가 보시면 원본 소스 코드와, 예제를 함께 보실 수 있습니다.
저는 실제로 콜백 함수들의 Safe하지 않은 코드 일부를 대체했는데요, 아무래도 Native-Pointer를 다루는 것에 비해 비용은 크지만 그만큼 얻는 것도 많은 만큼, Smart-Pointer나, Auto-Pointer 등과 함께 유용한 포인터 유틸 클래스로 사용 될 수 있지 않을까 생각이 드네요.


댓글