2010-06-11 2 views
1

더 큰 프로젝트를 해킹하는 동안 문제가 발생하여 간단한 테스트 사례를 만들었습니다. 뭔가 생략하지 않으면 테스트 코드가 제대로 작동하지만 우연히 작동하기 때문에이 접근법에 함정이 있는지 묻고 싶습니다.void *에서 캐스트/참조 해제 멤버 변수 포인터가 안전합니까?

회원 변수 (포인터) InObj가있는 OutObj가 있습니다. InObj에는 멤버 함수가 있습니다. void *와 같은 콜백 함수에이 멤버 변수 개체 (InObj)의 주소를 보냅니다. 이 객체의 유형은 결코 변경되지 않으므로 콜백 내에서 원래 유형으로 다시 작성하고 그 안에 aFunc 멤버 함수를 호출합니다. 이 예제에서 예상대로 작동하지만, 현재 작업하고있는 프로젝트에서는 그렇지 않습니다. 그래서 나는 무언가를 생략하거나 아마도 여기에 함정이있을 수 있으며 우연히 작동합니다. 다른하실 말씀 있나요? 많은 감사드립니다.

(원래 코드에있는 문제는 InObj.data가 쓰레기라는 것입니다.)

#include <stdio.h> 

class InObj 
{ 
public: 
int data; 
InObj(int argData); 
void aFunc() 
{ 
    printf("Inside aFunc! data is: %d\n", data); 
}; 
}; 

InObj::InObj(int argData) 
{ 
data = argData; 
} 

class OutObj 
{ 
public: 
InObj* objPtr; 
OutObj(int data); 
~OutObj(); 
}; 

OutObj::OutObj(int data) 
{ 
objPtr = new InObj(data); 
} 

OutObj::~OutObj() 
{ 
delete objPtr; 
} 

void callback(void* context) 
{ 
((InObj*)context)->aFunc(); 
} 

int main() 
{ 
OutObj a(42); 
callback((void*)a.objPtr); 
} 
+0

, 그것을 잘 보인다. 앱에서 "작동하지 않음"을 정의하십시오. – Stephen

+0

프로젝트에서 직면 한 정확한 문제점은 무엇입니까? – Canopus

+0

원래 코드에서 가지고있는 문제는 InObj.data가 쓰레기라는 것입니다. 그래서 이것이 괜찮아 보인다면 잠을 자고 코드에서 명백한 버그를 찾아야합니다. – Damien

답변

3

예, 안전합니다.

모든 유형의 포인터를 void 포인터로 변환하고 다시 포인터로 변환 할 수 있습니다.

에서void*까지의 변환은 내재적이므로 캐스트가 필요하지 않습니다.

+0

모든 포인터는 동일한 크기이며 동일한 데이터를 포함하고 있습니까? 유형은 다만 당신을 생각 나게하기위한 것이다. –

+1

@Brendan Long : 그건 사실이 아닙니다. 상속 계층 구조가 여러 개인 경우 올바른 vtbl 구조를 가리 키도록 실제로 포인터를 수정해야합니다. –

+4

@Brendan : 포인터가 많은 복잡합니다. 멤버에 대한 포인터는 객체에 대한 포인터와 크기가 같지 않을 수 있습니다. "작동 할 것"을 보장하는 것 중 하나는'T' 타입의 객체에 대한 포인터를 가지고 있다면'T *'를'void *'로 변환 한 다음'T *'로 되돌릴 수 있고 원래의 'T *'그리고 그 결과'T *'는 같은 객체를 가리킬 것이다. 그것은이 질문에있어서 정말로 중요한 규칙입니다. –

0

게시 된 내용은 안전하지 않은 유형의 안전 작업이 안전 할 경우 "안전"해야합니다. static_cast은 형식간에 이러한 안전하지 않은 변환을 수행 할 수 없기 때문에 C 캐스트 대신 static_cast으로 캐스팅을 대체합니다. static_cast으로 안전하지 않은 것을하려고하면 컴파일러는 추측을 떠나지 않고 알려줍니다.

(사이드 관련이없는 참고 : InObj의 생성자 대입보다는 초기화를 사용한다는 :

InObj::InObj(int argData) : data(argData) 
{ 
} 

)를 한 눈에