Runtime Type Identification(RTTI)
구 컴파일러에서는 지원하지 않을 수 있다.
dynamic_cast Operator
아래 코드는 아무런 compile error도 발생시키지 않는다. 과연 안전한 코드일까?
// Suppose a class hierarchy
class Base { ... };
class Derived1 : public Base { ... };
class Derived11 : public Derived1 { ... };
// Suppose the following pointers
Base* pb = new Base;
Base* pd1 = new Derived1;
Base* pd11 = new Derived11;
// Consider the following type casts
Derived11* p1 = (Derived11*)pd11; // 11->11
Derived11* p2 = (Derived11*)pb; // base->11
Derived1* p3 = (Derived1*)pd11; // 11->1
절대 아니다. 첫번째는 동일한 type이므로 안전하다. 세번째는 base class pointer로 derived class를 가리킬 수 있으니 괜찮다. 그러나 두번째는 runtime에서 오류가 발생하게 된다.
이러한 상황을 막기 위해 dynamic_cast 연산자를 사용한다. Typecast가 가능하다면 그대로 바꿔주고, 그렇지 않다면 0(null-pointer)를 반환한다.
Derived derived_obj;
Base base_obj;
Base *base_ptr_do = &derived_obj;
Base *base_ptr_bo = &base_obj;
Derived* dp_bp_do = dynamic_cast<Derived*>(base_ptr_do); // allowed
Derived* dp_bp_bo = dynamic_cast<Derived*>(base_ptr_bo); // return nullptr
dynamic_cast는 reference에도 사용할 수 있다. 다만 null-pointer에 해당하는 type이 reference value로 없기 때문에 0 대신 bad_cast를 반환한다.
#include <typeinfo> // for bad_cast
try {
Derived1& rs = dynamic_cast<Derived1&>(rb);
// ...
}
catch(bad_cast&) {
// ...
}
static_cast
C type cast와 유사하다.
기존의 표현이 가능한 type들 간에 변환만이 가능하다. 예를 들어, integer-enumeration, double-int, float-long 등 implicit type cast가 가능한 모든 경우가 이에 해당한다.
Base base;
Derived derived;
Base *pb = static_cast<Base*>(&derived); // valid upcast
Derived *pd = static_cast<Derived*>(&base); // valid downcast
const_cast
상수값(const)를 변수로 변환한다.
SomeClass obj;
const SomeClass *ptr = &obj;
SOmeClass *pb = const_cast<SomeClass*>(ptr);
// equivalent as
SomeClass *pb = (SomeClass*)(ptr);
// but it does not allow
AnotherClass *pb = (AnotherClass*)(ptr);
위와 같은 사례를 허용하지 않기 때문에 보다 안전하게 사용할 수 있다.
typeid operator
type_info structure
Questions?
Q1.
A1.
Q2.
A2.
[error-abort.cpp]: [error-return.cpp]: [error-try-catch]: [error-throw-object]: [bad-alloc.cpp]: