运行时类型识别
来源:互联网 发布:不安全的网络怎么连接 编辑:程序博客网 时间:2024/06/05 18:12
前言:当仅有一个指针或引用指向基类型时,利用运行时类型识别(RTTI)可以找到一个对象的动态类型。由于继承的层次结构的典型描述是基类在派生类之上,所以这种类型转换也称为向下类型转换.
- #ifndef __SECURITY_H
- #define __SECURITY_H
- #include <iostream>
- using namespace std;
- class Security
- {
- public:
- virtual ~Security()
- {}
- };
- class Stock:public Security
- {};
- class Bond:public Security
- {};
- class Investment:public Security
- {
- public:
- void Special()
- {
- cout << "Special Invenstment function" << endl;
- }
- };
- class Metal:public Investment
- {};
- #endif
- //.cpp
- #include "Security.h"
- #include <vector>
- int main()
- {
- vector<Security *> vecPort;
- vecPort.push_back(new Metal);
- vecPort.push_back(new Investment);
- vecPort.push_back(new Bond);
- vecPort.push_back(new Stock);
- for(vector<Security *>::iterator iter=vecPort.begin(); iter!=vecPort.end(); ++iter)
- {
- Investment *pInvest=dynamic_cast<Investment *>(*iter);
- if( pInvest )
- pInvest->Special();
- else
- cout << "not an Investment" << endl;
- }
- cout << "cast from intermediate pointer:" << endl;
- Security *s=new Metal;
- Investment *p=dynamic_cast<Investment *>(s);
- if( p )
- {
- cout << " it'an Investment" << endl;
- Metal *pMetal=dynamic_cast<Metal *>(p);
- if( pMetal )
- cout << " it's a Metal too!" << endl;
- }
- for(vector<Security *>::iterator iter=vecPort.begin(); iter!=vecPort.end(); ++iter)
- {
- delete *iter;
- *iter=NULL;
- }
- delete s;
- system("pause");
- return 0;
- }
输出结果为:
Special Invenstment function
Special Invenstment function
not an Investment
not an Investment
cast from intermediate pointer:
it'an Investment
it's a Metal too!
Press any key to continue . . .
从中可以看出,如果想要安全的进行向下类型转换,dynamic_cast要求使用的目标对象的类型是多态(polymorphic)的。这就要求该类必须有一个虚函数。
如果不用指针而用引用,由于没有诸如没有空引用这样的情况,这就需要用异常捕获来解决这个问题。bad_cast异常就这样诞生了。
- int main()
- {
- Metal m;
- //Stock m;
- Security &s=m;
- try
- {
- Investment &c=dynamic_cast<Investment &>(s);
- cout << "It's an Investment" << endl;
- }
- catch(bad_cast &e)
- {
- cout << "s is not an Investment: " << e.what() << endl;
- }
- //cout << "It's not a bond type" << endl;
- system("pause");
- return 0;
- }
- 输出结果如下:
- s is not an Investment: Bad dynamic
Press any key to continue . . .
如果需要获得一个关于运行时信息,就需要用typeid操作符来完成,这种操作符返回一个type_info类的对象,该对象给出了相关对象类型的信息,在MS中type_info声明如下:
- class type_info {
- public:
- virtual ~type_info();
- _CRTIMP_PURE bool __CLR_OR_THIS_CALL operator==(const type_info& rhs) const;
- _CRTIMP_PURE bool __CLR_OR_THIS_CALL operator!=(const type_info& rhs) const;
- _CRTIMP_PURE int __CLR_OR_THIS_CALL before(const type_info& rhs) const;
- _CRTIMP_PURE const char* __CLR_OR_THIS_CALL name(__type_info_node* __ptype_info_node = &__type_info_root_node) const;
- _CRTIMP_PURE const char* __CLR_OR_THIS_CALL raw_name() const;
- private:
- void *_m_data;
- char _m_d_name[1];
- __CLR_OR_THIS_CALL type_info(const type_info& rhs);
- type_info& __CLR_OR_THIS_CALL operator=(const type_info& rhs);
- _CRTIMP_PURE static const char *__CLRCALL_OR_CDECL _Name_base(const type_info *,__type_info_node* __ptype_info_node);
- _CRTIMP_PURE static void __CLRCALL_OR_CDECL _Type_info_dtor(type_info *);
- };
其中,
- /* Define _CRTIMP */
- #ifndef _CRTIMP
- #ifdef _DLL
- #define _CRTIMP __declspec(dllimport)
- #else /* ndef _DLL */
- #define _CRTIMP
- #endif /* _DLL */
- #endif /* _CRTIMP */
- #ifndef _CRTIMP_PURE
- #if defined(_M_CEE_PURE) || defined(_STATIC_CPPLIB)
- #define _CRTIMP_PURE
- #else
- #define _CRTIMP_PURE _CRTIMP
- #endif
- #endif
- #define __CLR_OR_THIS_CALL
现在就可以通过typeid操作符来获取一个对象的动态类型的名称了,见如下:
- #include <iostream>
- #include <typeinfo>
- using namespace std;
- struct PolyBase
- {
- virtual ~PolyBase()
- {}
- };
- struct PolyBer:PolyBase
- {
- };
- struct NonPolyBase
- {
- };
- struct NonpolyBer:NonPolyBase
- {
- };
- int main()
- {
- const PolyBase pd;
- const PolyBase *ppd=&pd;
- cout << typeid(&pd).name() << endl;
- cout << typeid(ppd).name() << endl;
- cout << typeid(*ppd).name() << endl;
- //cout << typeid(PolyBer).before(pd) << endl;
- cout << typeid(ppd).raw_name() << endl;
- cout << typeid(*ppd).raw_name() << endl;
- cout << boolalpha << (typeid(*ppd)==typeid(pd)) << endl;
- cout << boolalpha << (typeid(ppd)==typeid(pd)) << endl;
- cout << (typeid(PolyBer)==typeid(const PolyBer)) << endl;
- system("pause");
- return 0;
- }
输出如下:
struct PolyBase const *
struct PolyBase const *
struct PolyBase
.PBUPolyBase@@
.?AUPolyBase@@
true
false
true
Press any key to continue . . .
需要注意的是,RTTI忽略了顶层的const和volatile限定符,借助非多态类型,可以获得静态类型(该指针本身的类型)。RTTI仅仅能对完整的类型而工作,这就不能使用void型指针,一个void *是“无类型信息”。
当然,RTTI也可以和多重继承,模板一起工作,在这里就没有深入了。
总结:
实现RTTI的方法是,通过在类的虚函数表中放置一个附加的指针,这个指针指向那个特别类型的type_info结构,typeid()表达式的结果非常简单:虚函数表指针取得type_info指针,产生一个对type_info结构的引用。因为dynamic_cast使用的类库的程序必须从头至尾对一个基类表进行检查,dynamic_cast的开销就很有可能比typeid大,找到一个基类比一个派生类花销的时间就会更多。另外,dynamic_cast将任何一个类型于任何其他类型相比较,在同一层次中可以不受限制的进行类型比较,这就增加了程序的额外开销。
- 运行时类型识别
- 运行时类型识别
- 运行时类型识别
- 运行时类型识别
- 运行时类型识别
- 运行时类型识别
- 运行时类型识别
- 运行时类型识别
- 运行时类型识别
- 运行时类型识别(RTTI)
- RTTI 运行时类型识别
- 运行时类型识别(RTTI)
- 运行时类型识别RTTI
- RTTI 运行时类型识别
- RTTI 运行时类型识别
- RTTI 运行时类型识别
- RTTI 运行时类型识别
- RTTI运行时类型识别
- Compass开放源码JAVA搜索引擎框架
- 十大妙招让孩子对家长言听计从
- 使用 Nginx 提升网站访问速度
- 爬虫/蜘蛛程序的制作(C#语言)
- About the x window!
- 运行时类型识别
- Teradata and Data Warehouse Architectures
- 搜索引擎框架简介
- 什么是Web Service
- 诸葛亮:诫子书
- 如果学好SQL有啥好?
- java Thread:线程同步之互斥(1)
- 基于多点通信的PtoP聊天程序
- OGRE中实现鼠标选取