RTTI |
Run-Time Type Information |
运行时类型信息 |
Run-Time Type Identification |
运行时类型识别 |
C++ 通过下面两个 操作符 提供RTTI功能
typeid
dynamic_cast
其中:
typeid 返回 type_info 类的对象的一个引用
typeid 会抛出 bad_typeid 的异常
dynamic_cast 会抛出 bad_cast 异常
这3个类在头文件 typeinfo 中:
namespace std{ class type_info; class bad_cast; class bad_typeid; }
只有当 typeid 的参数是带虚函数的类类型的对象的时候,才返回动态类型信息.
例子:
#include <typeinfo> #include <iostream> #include <string> #include <vector> using std::cout; using std::endl; int func(int arg){return 0;} typedef int (*func_ptr)(int arg); class Base {public: Base(){}}; int main() { int integer(1); double real(1.0); int array[10]={1,2,3}; int * array_header = array; std::string string; std::vector<int> int_vector; func_ptr f = func; cout<<"integer : "<<typeid(integer).name() <<endl; cout<<"real : "<<typeid(real).name() <<endl; cout<<"array[10] : "<<typeid(array).name() <<endl; cout<<"array_header: "<<typeid(array_header).name()<<endl; cout<<"std::string : "<<typeid(string).name() <<endl; cout<<"std::vector : "<<typeid(int_vector).name() <<endl; cout<<"function : "<<typeid(func).name() <<endl; cout<<"function ptr: "<<typeid(f).name() <<endl; cout<<"custom class: "<<typeid(Base()).name() <<endl; cout<<std::endl; cout<<"int : "<<typeid(int).name() <<endl; cout<<"double : "<<typeid(double).name() <<endl; cout<<"std::vector : "<<typeid(std::vector<int>).name()<<endl; cout<<"Base : "<<typeid(Base).name() <<endl; cout<<"Base* : "<<typeid(Base*).name() <<endl; cout<<"Base& : "<<typeid(Base&).name() <<endl; return 0; }
结果:
g++ |
MSVC |
|
integer |
i |
int |
real |
d |
double |
array[10] |
A10_i |
int [10] |
array_header |
Pi |
int * |
std::string |
Ss |
class std::basic_string<char,struct std::char_traits<char> |
std::vector |
St6vectorIiSaIiEE |
class std::vector<int,class std::allocator<int> > |
function |
FiiE |
int __cdecl(int) |
function ptr |
PFiiE |
int (__cdecl*)(int) |
custom class |
F4BasevE |
class Base __cdecl(void) |
int |
i |
int |
double |
d |
double |
std::vector |
St6vectorIiSaIiEE |
class std::vector<int,class std::allocator<int> > |
Base |
4Base |
class Base |
Base* |
P4Base |
class Base * |
Base& |
4Base |
class Base |
对于每个类型,返回一个唯一的字符串,但该字符串的具体内容,与编译器实现有关。
在 typeid 中:
#include <typeinfo> #include <iostream> class Base1 { public: virtual void func1(){} }; class Base2 { public: virtual void func2(){} }; class D:public Base1, public Base2 {}; int main() { Base1 * b1 = new D; Base2 & b2 = dynamic_cast<Base2&>(*b1); std::cout << "Base1 " << uintptr_t(b1) <<" " << typeid(*b1).name() << std::endl << "Base2 " << uintptr_t(&b2) << " " <<typeid(b2).name() << std::endl; return 0; }
结果:
MSVC |
g++ |
Base1 208960 class D |
Base1 208088 1D |
C++0x 5.2.7:
The result of the expression dynamic_cast<T>(v) is the result of converting the expression v to type T. T shall be a pointer or reference to a complete class type, or “pointer to cv void.”
在dynamic_cast<T>(v) 中,T 是一个完整定义类的指针或引用,或者 void *。只能转换到 void *,不能从void*转换回来。
摘自 C++0x标准 18.7.1:
namespace std { class type_info { public: virtual ~type_info(); bool operator==(const type_info& rhs) const; bool operator!=(const type_info& rhs) const; bool before(const type_info& rhs) const; size_t hash_code() const throw(); const char* name() const; type_info(const type_info& rhs) = delete; // cannot be copied type_info& operator=(const type_info& rhs) = delete; // cannot be copied }; }
这里面,我们目前最感兴趣的是成员函数: name()
异常的定义(来自C++0x 18.7.3):
namespace std { class bad_typeid : public exception { public: bad_typeid() throw(); bad_typeid(const bad_typeid&) throw(); bad_typeid& operator=(const bad_typeid&) throw(); virtual const char* what() const throw(); }; }
例子:
#include <iostream> #include <typeinfo> class Polymorphic {virtual void Member(){}}; int main () { try { Polymorphic * pb = 0; std::cout << typeid(*pb).name(); } catch (std::bad_typeid& e) { std::cerr << "bad_typeid caught: " << e.what() << std::endl; } return 0; }
结果:
MSVC |
bad_typeid caught: Attempted a typeid of NULL pointer! |
g++ |
bad_typeid caught: std::bad_typeid |
异常产生条件:
比如,如果pb定义改为
int * pb = 0;
或 typeid 行改为
std::cout << typeid(pb).name();
则不会有异常发生。
异常的定义(来自C++0x 18.7.2):
namespace std { class bad_cast : public exception { public: bad_cast() throw(); bad_cast(const bad_cast&) throw(); bad_cast& operator=(const bad_cast&) throw(); virtual const char* what() const throw(); }; }
例子:
#include <iostream> #include <typeinfo> class Base {virtual void Member(){}}; class Derived : Base {}; int main () { try { Base b; Derived& rd = dynamic_cast<Derived&>(b); } catch (std::bad_cast& bc) { std::cerr << "bad_cast caught: " << bc.what() << std::endl; } return 0; }
结果:
MSVC |
bad_cast caught: Bad dynamic_cast! |
g++ |
bad_cast caught: std::bad_cast |