2013-07-28 7 views
5

는 그래서 가상 상속 static_cast를 사용하여 다운 캐스트하는 것은 불가능하지만, 어떻게 다음 업 캐스팅 할 수 있습니다 :static_cast를 가상 상속에 어떻게 사용할 수 있습니까?

[ derived part | base part ] 

나는 알고 upcasting 고려 : 개체의

class Base {...}; 
class Derived : public virtual Base {...}; 

... 

Derived *d = new Derived(); 
Base *b = static_cast<Base*>(d); 

메모리 레이아웃을 "안전"하지만 컴파일러는 상속이 가상 일 때 컴파일 타임에 기본 하위 객체에 대한 오프셋을 어떻게 알 수 있습니까? static_castvtable을 사용합니까?

class Third : public Derived {...}; 

... 

Derived *d = new Third();   // non-virtual upcast, no offset will be added 
Base *b = static_cast<Base*>(d); 

나도 같은 static_cast 라인을 사용하는이 시간이 있지만, 다른 인 Base 하위 개체에 오프셋 :

우리가 이런 일을 할 때 특히 혼란 (이것은 가상이 아니다 있습니다)! 개체의

메모리 레이아웃 : 그것은 d 지점에 객체의 실제 동적 타입에 의존하는 경우

[ derived part | third part | base part ] 

그래서 어떻게이 컴파일시에 결정할 수있다? 당신이 경우에 Derived에 대한 포인터가있을 때

답변

3

, 사용하는 것입니다 당신도 암시 적으로 Base에 대한 포인터로 Derived 포인터를 변환 할 수있는 Base 분명하다! 어떤 주소 조정이 필요한 경우 컴파일러는 임베디드 포인터, vtable 등을 사용하여이를 수행하는 방법을 파악합니다. 정확한 접근법은 C++ 표준에서 규정하지 않습니다. 정확한 결과는 ABI에 달려 있습니다. 예를 들어 Itanium C++ ABI의 경우 가상 테이블에 대한 오프셋은 가상 테이블에 저장되는 것처럼 보입니다.

+0

대개 내가 알고있는 것으로부터 오프셋은 vtable에 저장됩니다. 그러나 컴파일 타임에 정적으로 수행되는 방법에 대한 대답은 없습니다. 내가 제공 한 두 가지 사례를 살펴보면 어느 vtable에 올바른 오프셋이 있는지에 대한 질문이 제기됩니까? 어느 것이 컴파일러에서보아야합니까, Derived의 vtable 또는 Third 's vtable입니까? 분명히 vtable의 2 개 오프셋이 다르므로 올바른 vtable을 선택하는 것이 실행 시간 유형에 달려 있습니다. 이것이 왜 정적으로 수행되었는지 이해할 수없는 이유입니다. –

+0

static_cast에서 "static"은 컴파일 타임에 완료되었음을 의미하지 않습니다! 컴파일러가 컴파일 타임에 정보를 찾을 위치를 정적으로 파악할 수 있다는 것을 의미합니다. 예를 들어, vtable에서 오프셋을 검색하는 위치 또는 기본에 대한 포함 된 포인터가있는 위치를 알 수 있습니다 (가상 상속 구현 됨). 'dynamic_cast'처럼 vtable에서 어떤 클래스의 일치를 찾지 않을 것입니다. –

+0

static_cast에는 동적 인 측면이 있다는 것을 알 수 있습니다. 그 논리로 왜 static_cast는 가상 상속에서 다운 캐스팅을 할 수 없습니까? –