运行时类型识别
Posted joezzz
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了运行时类型识别相关的知识,希望对你有一定的参考价值。
1.RTTI
1)运行时类型识别RTTI(Run-Time Type Identification),它能够获取基类指针或引用所指向的对象的实际类型,在C++中,为了支持RTTI提供了两个运算符:typeid和dynamic_cast
2)
2.dynamic_cast
2.1概念
1)dynamic_cast运算符用于将基类的指针或引用安全地转换成派生类的指针或引用,这是安全的“向下转型”,至于“向上转型”,即派生类指针或引用转换为其基类指针或引用,本身就是安全的,尽管可以使用dynamic_cast进行转换,但这是没必要的, 普通的转换已经可以达到目的,毕竟使用dynamic_cast是有开销的
2)dynamic_cast使用形式:dynamic_cast<type*>(expression)
dynamic_cast<type&>(expression)
dynamic_cast<type&&>(expression) //右值引用
其中type必须是一个类类型,并且通常具有虚函数,否则编译会报错
2.2实例
对于“向下转型”有两种情况。一种是基类指针所指对象是派生类类型的,这种转换是安全的;另一种是基类指针所指对象为基类类型,在这种情况下dynamic_cast在运行时做检查,转换失败,抛出bad_cast异常,返回结果为0:
class Base { public: Base() {}; virtual void Show() { cout << "This is Base calss"; } }; class Derived :public Base { public: Derived() {}; void Show() { cout << "This is Derived class"; } }; int main() { //第一种情况,转换成功 Derived d; Base& base1 =d; Derived& der1 = dynamic_cast<Derived&>(base1); cout << "第一种情况:"; der1.Show(); cout << endl; //第二种情况 Base b; Base &base2 = b; cout << "第二种情况:"; try { Derived & der2 = dynamic_cast<Derived&>(base2); } catch (bad_cast) { cout << "转化失败,抛出bad_cast异常" << endl; } return 0; }
3.typeid
3.1概念
1)typeid运算符用于返回表达式的类型
2)typeid使用形式:typeid(expression);
如果表达式的类型是类且至少包含有一个虚函数,则typeid返回表达式的动态类型,需要在运行时计算;否则,typeid操作符返回表达式的静态类型,在编译时就可以计算
3)typeid运算符的返回值是type_info类的引用,ype_info类在头文件typeinfo中定义
4)type_info类提供了public虚析构函数,以使用户能够用其作为基类。它的默认构造函数和拷贝构造函数及赋值操作符都定义为private,所以不能定义或复制type_info类的对象,程序中创建type_info对象的唯一方法是使用typeid运算符
3.2实例
class Base {}; class Derived: public Base {}; int main() { Base b, *pb; pb = NULL; Derived d; cout << typeid(int).name() << endl << typeid(unsigned).name() << endl << typeid(long).name() << endl << typeid(unsigned long).name() << endl << typeid(char).name() << endl << typeid(unsigned char).name() << endl << typeid(float).name() << endl << typeid(double).name() << endl << typeid(string).name() << endl << typeid(Base).name() << endl << typeid(b).name()<<endl << typeid(pb).name()<<endl << typeid(Derived).name() << endl << typeid(d).name()<<endl << typeid(type_info).name() << endl; return 0; }
VS和GCC的结果:
class Base {}; class Derived : public Base {}; int main() { Base b, *pb; pb = NULL; Derived d; Base* pb2 = new Derived;//向上转型是安全的 Base& b2 = d; Base* pb3 = &d; cout << typeid(pb2).name() << endl//输出Base * << typeid(b2).name() << endl //输出Base,b2是一个类的引用,但这个类没有虚函数 << typeid(pb3).name() << endl//输出Base *,pb3是一个指针 << typeid(*pb3).name() << endl;//输出Base,*pb3是一个类,但这个类没有虚函数 return 0; }
现在对Base加上一个虚函数:
class Base { public: virtual void f() {} }; class Derived : public Base {}; int main() { Base b, *pb; pb = NULL; Derived d; Base* pb2 = new Derived;//向上转型是安全的 Base& b2 = d; Base* pb3 = &d; cout << typeid(pb2).name() << endl//输出Base *,pb2是一个指针,不是类对象 << typeid(b2).name() << endl //输出Derived,b2是一个基类的引用,这个类有虚函数,返回动态类型 << typeid(pb3).name() << endl//输出Base *,pb3是一个指针,不是类对象 << typeid(*pb3).name() << endl;//输出Derived,*pb3是一个类对象,这个类有虚函数,返回动态类型 return 0; }
以上是关于运行时类型识别的主要内容,如果未能解决你的问题,请参考以下文章
在 Python 多处理进程中运行较慢的 OpenCV 代码片段
linux打开终端如何启动scala,如何在终端下运行Scala代码片段?
Android 逆向Android 逆向通用工具开发 ( Android 平台运行的 cmd 程序类型 | Android 平台运行的 cmd 程序编译选项 | 编译 cmd 可执行程序 )(代码片段