概述
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 操作符
- 操作符 typeid 用法上类似于操作符 sizeof (?)
-
只有当 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 中:
- 数组不会退化为指针,比如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 | 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*转换回来。
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异常
参考
-
http://www.cplusplus.com/reference/std/typeinfo/bad_typeid
-
http://www.cplusplus.com/reference/std/typeinfo/bad_cast
FROM: http://blog.csdn.net/dbzhang800/article/details/6672591
最后
以上就是大气曲奇为你收集整理的typeid 与 dynamic_cast(C++学习)的全部内容,希望文章能够帮你解决typeid 与 dynamic_cast(C++学习)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复