2011-03-16 4 views
8

dynamic_cast을 사용하여 클래스 계층 구조 전반에 걸쳐 "크로스 캐스트"를 수행하는 것이 합법적이라는 것을 알고 있습니다. 내가 수업을 예를 들어, 다음과 같이한다 : I 유형 C의 객체 가리키는 것 A* 포인터가있는 경우크로스 캐스트가 작동 할 수 있는지 여부를 확인 하시겠습니까?

A B 
    \/
    C 

, 그때 나는에 대한 포인터를 얻을 수

A* aPtr = /* ... something that produces a C* ... */ 
B* bPtr = dynamic_cast<B*>(aPtr); 

을 사용할 수 있습니다 B 기본 개체는 C입니다.

나는 이것을 언급하는 이유는 내가 위의 코드를 작성할 때,이 컴파일러는 아직이 AB을 볼 비록 C의 정의를 볼 수없는 것을 가능성이 있다는 것입니다. 즉, 컴파일러가 AB 사이의 연결을 감지하지 못할 수도 있지만 어떤 경우에는 C 클래스가 존재하고 dynamic_cast 클래스가 성공할 수 있기 때문에 여전히 코드를 컴파일해야합니다.

이것은 내가 실수로 잘못된 유형의 객체로 크로스 캐스트 할 수 있다는 것을 의미합니다.

다음
A B D 
\/ 
    C 

, D는 어떤 임의의 관련이없는 클래스 : I는 다음과 같이 수업을한다고 가정하자. AD를 연결 할 수있는 방법이 없기 때문에

A* aPtr = /* ... get a C* pointer ... */ 
D* dPtr = dynamic_cast<D*>(aPtr); 

다음이 dynamic_cast 항상 런타임에 실패 할 것이다 : 나는 이런 식으로 뭔가를 작성하려고합니다. 내가 B을 사용하기 때문에 우연히 D을 사용하고 있다면, 컴파일러는 의미없는 캐스트가 있다는 것을 전혀 알려주지 않을 것입니다.

내 질문은 : 내가 런타임에 캐스트가 항상 실패한다는 것을 경고하기 위해 컴파일러를 얻을 수있는 방법이 있습니까? 언어 수준의 솔루션이나이를 감지 할 수있는 주요 컴파일러에 대한 일부 컴파일러 설정에 만족합니다. 외부 도구가 있다면 괜찮습니다. 이 오류 클래스를 포착 할 수 있는지 알고 싶습니다.

+0

이것은 꼭 링커 레벨 일 필요가 있습니까? 컴파일 할 때'A'와'D'에서 파생 된 클래스가 생성되지 않을 수도 있다는 것을 알지 못합니까? – Keith

+0

@ Keith- 당신이 전지용 컴파일러를 가지고 있지 않다면 확실히. 이봐 요, 그 중 하나를 원합니다 :-) – templatetypedef

+0

@ 키스 : 링커조차도 내 대답에 설명 된대로 모든 유형에 대한 완전한 정보를 가지고 있지 않을 수도 있습니다. –

답변

3

컴파일 타임에이를 감지 할 수 없습니다. 관계를 소개하는 클래스 C은 아직 작성되지 않은 동적으로로드 할 수있는 라이브러리에서 찾을 수 있으며 컴파일러는 그렇지 않다는 것을 증명할 수 없습니다.

몇 가지 예외가있을 수 있습니다.A에 전용 생성자 (또는 전용 소멸자) 만 있으면 컴파일러는 A에 의해 친구로 지정되지 않은 새 하위 클래스가 없음을 확신 할 수 있습니다.

+0

그건 사실입니다. 그러나 링커가 어떻게해서든지 "이봐,이게 의심 스럽다는 걸 알려주지?"라고 경고 할 수는 있겠 어? 결국 문제가되지 않을 수도 있습니다. – templatetypedef

+1

@templatetypedef :'dynamic_cast'는 템플릿 함수처럼 보이고 느껴지기 때문에 wrapper를 도입 할 수 있습니다. #define dynamic_cast checked_dynamic_cast'를 사용하여 강제로 래퍼를 사용하고 어떻게 든 템플릿의 모든 인스턴스화 된 버전의 목록을 가져올 수 있습니다 ? 상속 그래프를 얻는 것은 꽤 쉽습니다. 예를 들어 doxygen의 XML 출력을 포함하여 폭로하는 도구가 많이 있습니다. 해당 정보를 결합하고 몇 가지 휴리스틱을 적용하면 원하는 경고를 얻을 수 있습니다. –

-3

진실은 dynamic_cast을 사용할 때 클래스가 서로 관련이없는 경우에도 모든 다형성 포인터를 다형성 포인터에 캐스트 할 수 있습니다.

컴파일 시간을 확인하려면 많은 경우 다른 이유로 적합하지 않은 다른 캐스트 - static_cast 또는 암시 적 변환 -을 사용해야합니다.

dynamic_cast이 필요할 때 사용하는 솔루션은 dynamic_cast을 수행하는 템플릿 기능이며 null 포인터를 얻으면 예외를 throw합니다. 물론 이는 런타임 검사 일 뿐이지 만 오히려 안정적입니다.

+1

-1 : RTTI가 관련되어있는 경우에만 다형성 클래스를 다른 다형성 클래스로 dynamic_cast 할 수 있습니다. 그렇지 않으면 당신은 0 ptr (당신이 ptr로 형변환한다면)을 얻습니다, 그렇지 않으면 당신은 비 관련 다형성 클래스에 대한 ref로 형변환하면 bad_cast 예외를 얻습니다. – TrueY

0

동적 캐스팅의 전체적인 의미입니다. 동적입니다. 즉, 컴파일 타임이 아닌 런타임에서 확인됩니다.

컴파일러는 형 변환 된 클래스가 다형성인지 여부 만 확인합니다. 클래스가 다형성이 아닌 경우 런타임에서 캐스팅을 검사하는 데 필요한 정보가 충분하지 않습니다.

마지막으로 동적 캐스트 후에 프로그램은 수신 된 포인터가 null이 아닌지 확인해야합니다. 참조로 캐스트하면 std :: bad_cast를 catch해야합니다.

관련 문제