首页 > 代码库 > C++特殊工具与技术之RTTI
C++特殊工具与技术之RTTI
类型识别分为两种:一种以编译时类型识别,一种是运行时类型识别;
编译时类型识别:static_cast;
运行时类型识别(RTTI),C++通过下面连个操作符提供RTTi;
1)dynamic_cast操作符,将基类类型的指针或者引用安全地转换为派生类型的指针或者引用;
2)typeid操作符,返回指针或者引用所指对象的实际类型。
注意:若想要实现运行时类型识别,则要求其使用类型为 至少带有一个虚函数的类。对于其他类型,返回静态(即编译时)类型的信息。
为叙述方便,我们先把所用的类的代码写出,其中Animal为基类,Cat、Dog类为其派生类;
1 class Animal 2 { 3 public: 4 virtual ~Animal(){ } 5 virtual void run() 6 { cout<< "test" << endl; } 7 }; 8 9 class Cat:public Animal10 {11 public:12 void run()13 { cout << "Cat..." << endl; }14 };15 16 class Dog:public Animal17 {18 public:19 void run()20 { cout << "Dog.." << endl; } 21 };
一、static_cast(静态类型转换)的示例代码如下:
1 //static_cast发生在编译期间 2 #include <iostream> 3 #include <string> 4 #include <vector> 5 using namespace std; 6 7 int main(int argc, const char *argv[]) 8 { 9 Animal *base;10 Cat c;11 Dog d;12 base = &c;13 14 Cat *pc = static_cast<Cat*>(base);15 pc->run();//Cat... 16 17 Dog *pd = static_cast<Dog*>(base);18 pd->run();//Cat..打印的是实际指向的Cat对象19 return 0;20 }
注意:static_cast发生在编译期间,如果转化失败,那么会产生编译错误;若果编译成功,那么则转化成功。但是static_cast仍具有一定风险,尤其是向下塑形时。将Base*(基类指针)转化为Deriverd*(派生类指针)时,指针可以转化,但是指针未必指向Derived对象。
二、dynamic_cast(动态运行转换)示例代码如下:
转换引用:
//转换引用int main(int argc, const char *argv[]){ Cat c; Dog d; Animal &base = c;//引用时必须初始化 Cat &pc = dynamic_cast<Cat&>(base); cout << &pc << endl; //test_result 0xbfebb0 Dog &pd = dynamic_cast<Dog&>(base); cout << &pd << endl; //test_result bad_cast 与指针不同 return 0;}
转换指针:
//转换指针
int main(int argc, const char *argv[]){ Cat c; Dog d; Animal *base = &c; Cat *pc = dynamic_cast<Cat*>(base); cout << pc << endl; //打印指针的地址 //test_result oxbf94b98c Dog *pd = dynamic_cast<Dog*>(base); cout << pd << endl; //test_result 0 //转化未成功 return 0;}
注意:与dynamic_cast一起使用的指针必须是有效的--它必须为NULL,或者指向一个对象
dynamic_cast的具体实现:
1、dynamic_cast涉及运行时类型检查。如果绑定到引用或者指针的对象不是目标类型的对象 ,则dynamic_cast失败;
a)若是转换到指针类型 的dynamic_cast失败, 则dynamic_cast的结果为 0;
b)若是转换到引用类型 的dynamic_cast失败, 则抛出一个 bad_cast类型的异常。
步骤:dynamic_cast操作符一次执行两次操作;1:首先验证被请求的转换是否有效;2、在转换有效的情况下,操作符才实际进行转换。
C++primer 4th给出了使用dynamic_cast操作符的标准实践。
//指针情况、if(Derived *derivedPtr = dynamic_cast<Derived*>(basePtr){ //转化成功}else{ //失败处理}
引用情况:
//引用情况try { const Derived &d = dynamic_cast<const Derived&>(b); //成功情况 } catch(bad_cast) { //失败处理 }
这段代码的逻辑是非常严密的:
Derived *derivedPtr 的作用域只存在于if语句中
不可能在dynamic_cast和测试转换结果之间插入代码,因此不可能在测试转换成功之前使用derivedPtr。
三、typeid运行时类型转换;
typeid的作用机制和dynamic_cast类似。示例代码如下:
1 int main(int argc, const char *argv[]) 2 { 3 Cat c; 4 Dog d; 5 cout << typeid(string).name() << endl; 6 //类型名 7 cout << typeid(c).name() << endl;//3Cat 8 cout << typeid(d).name() << endl;//3Dog 9 Animal a;10 cout << typeid(a).name() << endl;//6Animal11 Animal *pa = &c;12 cout << typeid(*pa).name() << endl;//3Cat13 14 return 0;15 }
只有当typeid的操作数满足以下两个条件时,才返回动态类型信息,a)带有虚函数;b)是类类型的对象。另外,测试指针(相对于指针指向的对象)返回指针的静态的、编译时的类型。
RTTI的实例:C++ RTTI的使用
C++特殊工具与技术之RTTI
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。