dynamic_cast 연산자
피연산자가 변환 expression 형식의 개체에 type-id.
dynamic_cast < type-id > ( expression )
설명
type-id 에 대 한 포인터 또는 이전에 정의한 클래스 형식에 대 한 참조 또는 "포인터" void 하 여야 합니다.종류를 expression 경우에 대 한 포인터 이어야 합니다 type-id 경우는 포인터나 l-value입니다 type-id 에 대 한 참조입니다.
참조 하십시오 static_cast 에 대 한 정적 및 동적 캐스팅 변환 사이 및 사용 가능한 경우 차이점에 설명 합니다.
동작에는 두 가지 주요 변경 사항 dynamic_cast 관리 되는 코드에서:
dynamic_castboxed 열거형의 내부 형식에 대 한 포인터를이 변환 된 포인터 대신 0 반환 런타임에 실패 합니다.
dynamic_cast더 이상 예외를 throw 하면 type-id 실행 시 실패 캐스팅은 값 형식에 내부 포인터입니다.이제 캐스팅 throw 하는 대신 포인터가 0 값을 반환 합니다.
경우 type-id 에 명확한 액세스할 수 직접 또는 간접 기본 클래스의 포인터입니다 expression, 고유한 하위 개체 형식에 대 한 포인터 type-id 결과입니다.예를 들면 다음과 같습니다.
// dynamic_cast_1.cpp
// compile with: /c
class B { };
class C : public B { };
class D : public C { };
void f(D* pd) {
C* pc = dynamic_cast<C*>(pd); // ok: C is a direct base class
// pc points to C subobject of pd
B* pb = dynamic_cast<B*>(pd); // ok: B is an indirect base class
// pb points to B subobject of pd
}
파생 클래스에서 파생 된 클래스에는 클래스 계층 구조 위로 포인터를 이동 하기 때문에 이러한 유형의 변환에 "업캐스팅은" 라고 합니다.업캐스팅이는 암시적 변환입니다.
경우 type-id 는 void * 실제 유형을 확인 하는 런타임 검사가 수행 됩니다 expression.결과 전체 개체를 가리키는 포인터입니다 expression.예를 들면 다음과 같습니다.
// dynamic_cast_2.cpp
// compile with: /c /GR
class A {virtual void f();};
class B {virtual void f();};
void f() {
A* pa = new A;
B* pb = new B;
void* pv = dynamic_cast<void*>(pa);
// pv now points to an object of type A
pv = dynamic_cast<void*>(pb);
// pv now points to an object of type B
}
경우 type-id 아닙니다 void * 런타임 검사 한 개체를 가리키는 경우를 참조 하십시오. expression 가 가리키는 형식으로 변환 될 수 있습니다 type-id.
경우의 종류 expression 기본 클래스 형식입니다 type-id, 하는 런타임 검사가 수행 됩니다 expression 실제로 가리키는 형식의 전체 개체에 type-id.이 true 이면 결과 완전 한 개체의 형식에 대 한 포인터입니다. type-id.예를 들면 다음과 같습니다.
// dynamic_cast_3.cpp
// compile with: /c /GR
class B {virtual void f();};
class D : public B {virtual void f();};
void f() {
B* pb = new D; // unclear but ok
B* pb2 = new B;
D* pd = dynamic_cast<D*>(pb); // ok: pb actually points to a D
D* pd2 = dynamic_cast<D*>(pb2); // pb2 points to a B not a D
}
이 유형의 변환 이라고는 "다운" 클래스에 지정 된 클래스의 클래스 계층 구조를 포인터를 이동 하기 때문에 여기에서 파생 됩니다.
다중 상속의 경우에는 모호성을 가능성이 발생 합니다.다음 그림에 클래스 계층 구조를 고려해 야 합니다.
CLR 형식에 대 한 dynamic_cast 변환을 암시적으로 수행할 수 있다면 아무 나는 MSIL의 결과 isinst 동적 검사를 수행 하 고 반환 명령 nullptr 변환이 실패 한 경우.
다음 샘플 사용 dynamic_cast 특정 형식의 인스턴스는 클래스 인지 확인 합니다.
// dynamic_cast_clr.cpp
// compile with: /clr
using namespace System;
void PrintObjectType( Object^o ) {
if( dynamic_cast<String^>(o) )
Console::WriteLine("Object is a String");
else if( dynamic_cast<int^>(o) )
Console::WriteLine("Object is an int");
}
int main() {
Object^o1 = "hello";
Object^o2 = 10;
PrintObjectType(o1);
PrintObjectType(o2);
}
다중 상속을 보여 주는 클래스 계층 구조
개체 형식에 대 한 포인터 D 를 안전 하 게 캐스팅 될 수 있습니다 B 또는 C.그러나 경우 D 가리키도록 캐스팅는 A 개체는 인스턴스를 A 될 수 있습니까?이 모호한 캐스팅 오류가 발생 합니다.이 문제를 해결 하려면 두 개의 모호 하지 않은 캐스트를 수행할 수 있습니다.예를 들면 다음과 같습니다.
// dynamic_cast_4.cpp
// compile with: /c /GR
class A {virtual void f();};
class B {virtual void f();};
class D : public B {virtual void f();};
void f() {
D* pd = new D;
B* pb = dynamic_cast<B*>(pd); // first cast to B
A* pa2 = dynamic_cast<A*>(pb); // ok: unambiguous
}
가상 기본 클래스를 사용 하면 더 이상 모호함을 알아낼 수 있습니다.다음 그림에 클래스 계층 구조를 고려해 야 합니다.
가상 기본 클래스를 보여 주는 클래스 계층 구조
이 계층 구조에서 A 가상 기본 클래스입니다.참조 하십시오 가상 기본 클래스 가상 기본 클래스를 정의 합니다.클래스의 인스턴스가 지정 E 가리키는 포인터는 A 하위 개체에는 dynamic_cast 에 대 한 포인터를 B 모호성 때문에 실패 합니다.먼저 다시 전체를 캐스팅 해야 E 개체를 다음 계층 구조를 다시 해 올바른 도달 모호 하지 않은 방식으로 작동 B 개체입니다.
다음 그림에 클래스 계층 구조를 고려해 야 합니다.
클래스 계층 구조 복제 표시 된 기본 클래스
형식의 개체를 지정 된 E 와에 대 한 포인터는 D 하위 개체를 탐색 합니다,의 D 하위 개체의 맨 왼쪽에 A subobject, 세 가지 변환 될 수 있습니다.수행할 수 있습니다는 dynamic_cast 에서 변환은 D 에 대 한 포인터는 E 포인터를 다음으로 변환 (두 dynamic_cast 또는 암시적 변환)에서 E 에 B, 및 마지막으로 암시적 변환이 B 에 A.예를 들면 다음과 같습니다.
// dynamic_cast_5.cpp
// compile with: /c /GR
class A {virtual void f();};
class B : public A {virtual void f();};
class C : public A { };
class D {virtual void f();};
class E : public B, public C, public D {virtual void f();};
void f(D* pd) {
E* pe = dynamic_cast<E*>(pd);
B* pb = pe; // upcast, implicit conversion
A* pa = pb; // upcast, implicit conversion
}
dynamic_cast 연산자도 사용할 수 있습니다 "크로스 캐스팅" 수행할 수 같은 클래스 계층 구조를 사용 하 여 포인터를 예를 들어에서 캐스팅할 수 있습니다는 B subobject에 있는 D subobject에서 완전 한 개체 형식으로 E.
크로스 캐스팅을 고려할 때는 실제로 변환에 대 한 포인터를 수행할 수 있습니다 D 맨 왼쪽 포인터를 A 는 두 단계에서 하위 개체입니다.십자형에서 캐스팅을 수행할 수 있습니다 D 에 B, 다음 암시적 변환이 B 에 A.예를 들면 다음과 같습니다.
// dynamic_cast_6.cpp
// compile with: /c /GR
class A {virtual void f();};
class B : public A {virtual void f();};
class C : public A { };
class D {virtual void f();};
class E : public B, public C, public D {virtual void f();};
void f(D* pd) {
B* pb = dynamic_cast<B*>(pd); // cross cast
A* pa = pb; // upcast, implicit conversion
}
Null 포인터 값이 null 포인터 값을 대상 형식으로 변환 됩니다 dynamic_cast.
사용 하는 경우 dynamic_cast < type-id > ( expression )경우, expression 형식으로 안전 하 게 변환할 수 없습니다. type-id, 런타임 검사 실패 캐스팅 하면 됩니다.예를 들면 다음과 같습니다.
// dynamic_cast_7.cpp
// compile with: /c /GR
class A {virtual void f();};
class B {virtual void f();};
void f() {
A* pa = new A;
B* pb = dynamic_cast<B*>(pa); // fails at runtime, not safe;
// B not derived from A
}
실패 한 포인터 형식으로 캐스팅은 null 포인터입니다.실패 한 캐스트 형식을 throw를 참조 하는 bad_cast 예외. 경우 expression 가리키고 하거나 유효한 개체를 참조 하지는 __non_rtti_object 예외가 throw 됩니다.
참조 하십시오 typeid 에 대 한 설명을 __non_rtti_object 예외입니다.
예제
다음 샘플 (C 구조체) 개체에 기본 클래스 (구조체 A) 포인터를 만듭니다.이 더한 존재 사실을 가상 함수, 런타임 다형성을 있습니다.
샘플 또한 계층 구조에서 가상 함수를 호출합니다.
// dynamic_cast_8.cpp
// compile with: /GR /EHsc
#include <stdio.h>
#include <iostream>
struct A {
virtual void test() {
printf_s("in A\n");
}
};
struct B : A {
virtual void test() {
printf_s("in B\n");
}
void test2() {
printf_s("test2 in B\n");
}
};
struct C : B {
virtual void test() {
printf_s("in C\n");
}
void test2() {
printf_s("test2 in C\n");
}
};
void Globaltest(A& a) {
try {
C &c = dynamic_cast<C&>(a);
printf_s("in GlobalTest\n");
}
catch(std::bad_cast) {
printf_s("Can't cast to C\n");
}
}
int main() {
A *pa = new C;
A *pa2 = new B;
pa->test();
B * pb = dynamic_cast<B *>(pa);
if (pb)
pb->test2();
C * pc = dynamic_cast<C *>(pa2);
if (pc)
pc->test2();
C ConStack;
Globaltest(ConStack);
// will fail because B knows nothing about C
B BonStack;
Globaltest(BonStack);
}