2008-11-22 3 views
0

포인터를 long (SendMessage()) 으로 변환해야하며 변수가 올바른지 여부를 안전하게 확인하고 싶습니다. 그래서 내가 dynamic_cast 일을 생각하고 있었지만 그것은 가상이 아닌 클래스에서는 작동하지 않습니다. 그럼 typeid하고 생각했지만 그것이 기본으로 파생 된 var 전달할 때까지 작동합니다.X가 typeid를 통해 Y를 파생하는지 확인하십시오.

포인터가 런타임 중에 예상하는지 확인하는 방법이 있습니까? 포인터가 특정 기준에서 파생 된 유형인지 확인하기 위해 typeid를 사용할 수있는 방법이 있습니까?

+1

질문 텍스트가 질문 제목과 어떤 식 으로든 어떤 관련이 있습니까? –

+1

가난한 디자인이라고 생각합니다. 가상 기능이 전혀 없다면 왜 기본 클래스를 알아야합니까? 당신이 안전하게 추방되거나 다른 어떤 것도 할 수있는 것처럼 아닙니다. 또한 기본 클래스를 작성할 때 최소한 가상 dtor를 사용하는 것이 좋습니다. –

+0

http://stackoverflow.com/questions/311102/safely-checking-the-type-of-a-variable과 같은 질문이 아니라 다른 제안 된 접근 방식이 있습니까? –

답변

1

당신이 가지고있는 것이 모두 long 인 경우, 실제로 할 수있는 일이 많지 않습니다. 임의의 숫자가 유효한 메모리 주소를 나타내는 지 여부를 결정하는 일반적인 방법은 없습니다. 유효한 메모리 주소라는 것을 알고 있더라도 포인터가 가리키는 대상의 유형을 판별 할 수있는 방법은 없습니다. 주소가 long으로 변경되기 전에 실제 유형을 확신 할 수없는 경우 캐스팅 할 계획이있는 유형으로 long을 전송하는 것이 안전하다고 확신 할 수 없습니다.

메시지를 보낸 사람이 유효한 값을 보낸 것으로 신뢰할 수 있습니다. 당신이 할 수있는 최선의 방법은 가짜 값을받을 때 자신의 프로그램에 미치는 결과를 줄이기 위해 몇 가지 예방 조치를 취하는 것입니다.

0

PTLib (http://sourceforge.net/projects/opalvoip/)는 PCLASSINFO 매크로를 사용하여 클래스 간의 관계를 정의합니다. 이것은 IsDescendant 및 GetClass와 같은 기능을 제공합니다.

아마도 비슷한 것을 구현할 수 있습니다.

0

dynamic_cast는 가상 메소드 테이블의 서명을 확인하여 작동합니다. 가상 메소드가없는 경우에는 VMT가 없기 때문에 dynamic_cast가 작동하지 않는다고 말합니다. 그러나 VMT가없는 경우에는 가리키고있는 객체에 대한 지식이 전혀 없습니다.

가장 좋은 방법은 더미인데도 포인터가 적어도 하나의 가상 메소드가있는 클래스에 있어야한다는 것입니다. 그러면 동적 캐스트가 작동합니다.

0

아직 귀하의 질문에 대해 이해가 가지 않습니다.

  • 는, 당신이 길고 뒷면에 ​​캐스팅하면 같은 값을 얻을 것이라고 확신 할 수 있는지 여부 "규칙 포인터 사용하기위한"MS-사이트를 다른 답변자를 연결 감안할보기 Safely checking the type of a variable
    경우, 캐스트 할 오른쪽 유형은 UINT_PTR입니다. 따라서 UINT_PTR v = reinterpret_cast<UINT_PTR>(ptr);을 정수형으로 형변환하고 역순으로 포인터를 다시 캐스팅하십시오. C++ 표준은 원래 값이 복원됨을 보증합니다. (내가 그것에 대한 나의 설명을 위해 위에서 준 링크를 보라). MS 사이트에서 WPARAM과 LPARAM은 플랫폼에 따라 크기가 바뀌 었다고합니다. 따라서 변수 vSendMessage을 사용할 수 있습니다.
  • 포인터 (일부 포인터 유형으로 변환 됨)가 어떤 개체를 가리키는 지 여부를 다른 쪽에서 확인할 수있는 방법은 수 없습니다. 어떤 포인터 유형이 포인터를 보내는 데 사용되었는지 확실하지 않으므로 포인터가 가리키는 동적 유형이 수신 측에서 확인할 수 없습니다. 포인터가 보낸 사람쪽에있는 유형을 알고 있으면 처음에는 필요하지 않습니다.
1

typeid를 사용할 수 없습니다. 유효한 포인터 대신 가비지를 얻으면 액세스 위반이 발생하므로 무의미합니다.

SendMessage 및 메시지를 처리하는 코드를 단일 형식의 안전한 인터페이스로 래핑합니다. 이렇게하면 예기치 않은 것을 SendMessage에 전달할 수 없으며 수신 측에서 검사가 필요하지 않습니다.

C++ 유형 시스템은 컴파일 할 때 작동합니다. 포인터를 long으로 캐스트하면 모든 유형 정보가 손실됩니다. long은 메모리에 너무 많은 비트입니다. 객체를 가리키고 있음을 확인할 수있는 방법이 없습니다.

3

SendMessage()에 대한 참조로 인해 MS Windows와 같은 소리가 들리고 플랫폼은 Rules for Using Pointers (Windows)입니다. PtrToLongPtrToUlong 함수 및 이와 유사한 상황에서 Microsoft에서 제공하는 기타 사항에 대해 자세히 설명합니다.

0

Windows에서 MFC는 주어진 포인터가 유효한 메모리 위치를 가리키는 지 확인하는 방법을 제공합니다 (segfault를 트래핑하여 수행). 함수 이름은 기억이 나지 않지만 거기에 있습니다. 그래도 가리키는 메모리의 내용이 유효하다는 것을 보장하지는 않습니다. VMT가 유효하지 않아 코드가 손상 될 수 있습니다. 물론 segfault를 트랩 할 수도 있습니다 (see MS Knowledge Base)

어떤 것이 유형에 속하는지 확인하는 데는 기본 클래스가 있어야합니다. 기본 클래스의 소멸자를 "가상"으로 만들면 모든 파생 클래스에는 VMT가 포함됩니다.

VMT를 피해야 만하는 경우에는 MS Windows 이벤트의 이벤트 유형과 같이 사용자가 처리하는 내용을 알려주는 일종의 descriminator가 있어야합니다.

관련 문제