RTTI |
Run-Time Type Information |
运行时类型信息 |
Run-Time Type Identification |
运行时类型识别 |
C++ 通过下面两个 操作符 提供RTTI功能
其中:
-
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> ,class s td::allocator<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 中:
- 数组不会退化为指针,比如int array[10]
- 函数不会退化为指针, func 和 f
- 顶层cv-qualifiers会被忽略 typeid(D) == typeid(const D);
- ...
dynamic_cast 操作符
#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 Base2 208964 class D |
Base1 208088 1D Base2 208092 1D |
C++0x 5.2.7:
在dynamic_cast<T>(v) 中,T 是一个完整定义类的指针或引用,或者 void *。只能转换到 void *,不能从void*转换回来。
type_info 类
摘自 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()
bad_typeid 类
异常的定义(来自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();
则不会有异常发生。
bad_cast 类
异常的定义(来自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 |
- 对指针cast失败,返回一个空指针
- 对引用cast失败,则抛出bad_cast异常
参考
FROM: http://blog.csdn.net/dbzhang800/article/details/6672591