여기에 개요입니다 static_cast<>
그리고 dynamic_cast<>
그들은 포인터에 특별히을 관련이있다. 이것은 101 수준의 런 다운이며 모든 복잡한 사항을 다루지는 않습니다.
static_cast <유형 *> (ptr)
이것은 포인터를 가져 와서 ptr
포인터 타입으로 안전하게 캐스트하려고합니다 Type*
. 이 캐스트는 컴파일 타임에 수행됩니다. 유형 유형이 관련된 경우에만 캐스트를 수행합니다. 유형이 관련이 없으면 컴파일러 오류가 발생합니다. 예를 들면 다음과 같습니다.
class B {};
class D : public B {};
class X {};
int main()
{
D* d = new D;
B* b = static_cast<B*>(d); // this works
X* x = static_cast<X*>(d); // ERROR - Won't compile
return 0;
}
dynamic_cast <유형 *> (ptr)
이것은 포인터를 다시 가져 와서 ptr
타입 포인터로 안전하게 캐스트합니다 Type*
. 그러나이 캐스트는 컴파일 타임이 아니라 런타임에 실행됩니다. 이것은 런타임 캐스트이므로 다형성 클래스와 결합 할 때 특히 유용합니다. 실제로, certian의 경우 캐스트가 합법적이 려면 클래스 가 다형성 이어야합니다 .
캐스트는 기본에서 파생으로 (B2D) 또는 파생에서 기본으로 (D2B) 두 방향 중 하나로 진행할 수 있습니다. D2B 캐스트가 런타임에 작동하는 방식을 보는 것은 간단합니다. 하나는 ptr
에서 파생 된 Type
또는 아니었다. D2B dynamic_cast <> s의 경우 규칙은 간단합니다. 다른 것에 무언가를 캐스팅하려고 할 수 있으며 ptr
실제로에서 파생 된 경우에서 포인터를 다시 Type
얻을 수 Type*
있습니다 dynamic_cast
. 그렇지 않으면 NULL 포인터가 표시됩니다.
그러나 B2D 캐스트는 조금 더 복잡합니다. 다음 코드를 고려하십시오.
#include <iostream>
using namespace std;
class Base
{
public:
virtual void DoIt() = 0; // pure virtual
virtual ~Base() {};
};
class Foo : public Base
{
public:
virtual void DoIt() { cout << "Foo"; };
void FooIt() { cout << "Fooing It..."; }
};
class Bar : public Base
{
public :
virtual void DoIt() { cout << "Bar"; }
void BarIt() { cout << "baring It..."; }
};
Base* CreateRandom()
{
if( (rand()%2) == 0 )
return new Foo;
else
return new Bar;
}
int main()
{
for( int n = 0; n < 10; ++n )
{
Base* base = CreateRandom();
base->DoIt();
Bar* bar = (Bar*)base;
bar->BarIt();
}
return 0;
}
main()
어떤 종류의 객체 CreateRandom()
가 반환 되는지 알 수 없으므로 C 스타일 캐스트 Bar* bar = (Bar*)base;
는 유형 안전하지 않습니다. 이 문제를 어떻게 해결할 수 있습니까? 한 가지 방법은 부울 같은 기능을 추가하는 것입니다 AreYouABar() const = 0;
기본 클래스에 반환 true
에서 Bar
와 false
에서 Foo
. 그러나 다른 방법이 있습니다 : use dynamic_cast<>
:
int main()
{
for( int n = 0; n < 10; ++n )
{
Base* base = CreateRandom();
base->DoIt();
Bar* bar = dynamic_cast<Bar*>(base);
Foo* foo = dynamic_cast<Foo*>(base);
if( bar )
bar->BarIt();
if( foo )
foo->FooIt();
}
return 0;
}
캐스트는 런타임에 실행되며 객체를 쿼리하여 (지금 방법에 대해 걱정할 필요가 없음) 원하는 유형인지 묻습니다. 그렇다면 dynamic_cast<Type*>
포인터를 반환합니다. 그렇지 않으면 NULL을 반환합니다.
이 base-to-derived 캐스팅이 dynamic_cast<>
, Base, Foo 및 Bar를 사용하여 작동 하려면 Standard가 polymorphic 유형을 호출해야합니다 . 다형성 유형이 되려면 클래스에 virtual
함수가 하나 이상 있어야합니다 . 클래스가 다형성 유형이 아닌 경우 기본에서 파생 된 사용은 dynamic_cast
컴파일되지 않습니다. 예:
class Base {};
class Der : public Base {};
int main()
{
Base* base = new Der;
Der* der = dynamic_cast<Der*>(base); // ERROR - Won't compile
return 0;
}
가상 dtor와 같은 기본에 가상 함수를 추가하면 기본 및 Der 다형성 유형이 모두 생성됩니다.
class Base
{
public:
virtual ~Base(){};
};
class Der : public Base {};
int main()
{
Base* base = new Der;
Der* der = dynamic_cast<Der*>(base); // OK
return 0;
}
dynamic_cast<>
작동 하는 방식 (또는 C ++ 작동 량)에 대한 좋은 아이디어를 얻으려면 Lippman의 "C ++ 개체 모델 내부"라는 좋은 책을 읽어보십시오. 또한 Stroustrup의 "C ++의 디자인과 진화"및 "C ++ 프로그래밍 언어"책은 훌륭한 자료이지만 Lippman의 책은 C ++이 '뒤에서'작동하는 방식에 전념합니다.