RTTI运行时类型识别

概述

RTTI(Run-Time Type Identification),通过运行时类型信息程序能够使用基类的指针或引用来检查这些指针或引用所指的对象的实际派生类型。。面向对象的编程语言,像C++,Java,delphi都提供了对RTTI的支持。

本文主要介绍C++的RTTI以及MFC相关的RTTI。

1、C++

RTTI提供了以下两个非常有用的操作符:
1)typeid操作符,返回指针和引用所指的实际类型。
2)dynamic_cast操作符,将基类类型的指针或引用安全地转换为派生类型的指针或引用。
 1 #include <iostream>
 2 using namespace std;
 3 class Base {};
 4 class Derived: public Base {};
 5 int main()
 6 {
 7     Base b, *pb;
 8     pb = NULL;
 9     Derived d;
10     cout << typeid(int).name() << endl << typeid(unsigned).name() << endl
11          << typeid(long).name() << endl << typeid(unsigned long).name() << endl
12          << typeid(char).name() << endl << typeid(unsigned char).name() << endl
13          << typeid(float).name() << endl << typeid(double).name() << endl
14          << typeid(string).name() << endl << typeid(Base).name() << endl
15          << typeid(b).name()<<endl << typeid(pb).name()<<endl
16          << typeid(Derived).name() << endl << typeid(d).name()<<endl
17          << typeid(type_info).name() << endl;
18          
19     return 0;
20 }

 

2、模拟MFC

有些人会有疑问,C++已经有RTTI了,为什么MFC还要实现一套自己的RTTI,原因时MFC开发的时候,C++标准还比较老,还没有这方面的内容,所以MFC自己实现了一套。以下模拟MFC的方式实现一套RTTI。

----------------------------runtimeclass.h------------------------------

 

 1 #ifndef _RTTIAPP_RUNTIMECLASS_H
 2 #define _RTTIAPP_RUNTIMECLASS_H
 3 
 4 #include "datatype.h"
 5 
 6 class CObject;
 7 
 8 struct CRuntimeClass
 9 {
10     // Attributes
11     LPCSTR m_lpszClassName;
12     int m_nObjectSize;
13     UINT m_wSchema; // schema number of the loaded class
14     CObject* (PASCAL* m_pfnCreateObject)(); // NULL => abstract class
15     CRuntimeClass* m_pBaseClass;
16 
17     // CRuntimeClass objects linked together in simple list
18     static CRuntimeClass* pFirstClass; // start of class list
19     CRuntimeClass* m_pNextClass;       // linked list of registered classes
20 };
21 
22 struct AFX_CLASSINIT
23 { AFX_CLASSINIT(CRuntimeClass* pNewClass); };
24 
25 #define RUNTIME_CLASS(class_name) \
26     (&class_name::class##class_name)
27 
28 #define DECLARE_DYNAMIC(class_name) \
29 public: \
30     static CRuntimeClass class##class_name; \
31     virtual CRuntimeClass* GetRuntimeClass() const;
32 
33 #define _IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, wSchema, pfnNew) \
34     static char _lpsz##class_name[] = #class_name; \
35     CRuntimeClass class_name::class##class_name = { \
36     _lpsz##class_name, sizeof(class_name), wSchema, pfnNew, \
37     RUNTIME_CLASS(base_class_name), NULL }; \
38     static AFX_CLASSINIT _init_##class_name(&class_name::class##class_name); \
39     CRuntimeClass* class_name::GetRuntimeClass() const \
40 { return &class_name::class##class_name; } \
41 
42 #define IMPLEMENT_DYNAMIC(class_name, base_class_name) \
43     _IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, 0xFFFF, NULL)
44 
45 #endif

 


-------------------------------runtimeclass.cpp---------------------------------------------

 

1 #include "runtimeclass.h"
2 
3 CRuntimeClass* CRuntimeClass::pFirstClass = NULL;
4 
5 AFX_CLASSINIT::AFX_CLASSINIT(CRuntimeClass* pNewClass)
6 {
7     pNewClass->m_pNextClass = CRuntimeClass::pFirstClass;
8     CRuntimeClass::pFirstClass = pNewClass;
9 }

 

 

------------------------------object.h----------------------------------------------------------

 

 1 #ifndef _RTTIAPP_OBJECT_H_
 2 #define _RTTIAPP_OBJECT_H_
 3 
 4 #include "runtimeclass.h"
 5 
 6 class CObject
 7 {
 8 public:
 9     CObject::CObject()  {
10     }
11     CObject::~CObject() {
12     }
13 
14     virtual CRuntimeClass* GetRuntimeClass() const;
15     BOOL IsKindOf(const CRuntimeClass* pClass) const;
16 
17 public:
18     static CRuntimeClass classCObject;
19 };
20 
21 #endif

 


-------------------------------------------object.cpp----------------------------

 

 1 #include "object.h"
 2 #include "runtimeclass.h"
 3 
 4 static char szCObject[] = "CObject";
 5 struct CRuntimeClass CObject::classCObject =
 6 { szCObject, sizeof(CObject), 0xffff, NULL, NULL };
 7 
 8 static AFX_CLASSINIT _init_CObject(&CObject::classCObject);
 9 
10 CRuntimeClass* CObject::GetRuntimeClass() const
11 {
12     return &CObject::classCObject;
13 }
14 
15 BOOL CObject::IsKindOf(const CRuntimeClass* pClass) const
16 {
17     CRuntimeClass* pClassThis = GetRuntimeClass();
18     while (pClassThis != NULL)
19     {
20         if (pClassThis == pClass)
21             return TRUE;
22         pClassThis = pClassThis->m_pBaseClass;
23     }
24     return FALSE;       // walked to the top, no match
25 }

 

 

---------------------------------main.cpp-------------------------------------

 

 1 #include <iostream>
 2 #include "object.h"
 3 #include "runtimeclass.h"
 4 
 5 using namespace std;
 6 
 7 class CGraphics : public CObject
 8 {
 9     DECLARE_DYNAMIC(CGraphics)
10 };
11 
12 class CLine : public CGraphics
13 {
14     DECLARE_DYNAMIC(CLine)
15 };
16 
17 class CRectangle : public CGraphics
18 {
19     DECLARE_DYNAMIC(CRectangle)
20 };
21 
22 IMPLEMENT_DYNAMIC(CRectangle, CGraphics)
23 IMPLEMENT_DYNAMIC(CLine, CGraphics)
24 IMPLEMENT_DYNAMIC(CGraphics, CObject)
25 
26 int main()
27 {
28     CRectangle *pRect = new CRectangle();
29     CLine *pLine = new CLine();
30 
31     cout << "pRect->IsKindOf(RUNTIME_CLASS(CGraphics)): " << pRect->IsKindOf(RUNTIME_CLASS(CGraphics)) <<endl; 
32 
33     cout << "pLine->IsKindOf(RUNTIME_CLASS(CGraphics)): " << pLine->IsKindOf(RUNTIME_CLASS(CGraphics)) <<endl; 
34 
35     cout << "pLine->IsKindOf(RUNTIME_CLASS(CRectangle)): " << pLine->IsKindOf(RUNTIME_CLASS(CRectangle)) <<endl; 
36 }

 


运行结果


 

完整源码

http://git.oschina.net/zhujf21st/RTTIApp

3、直接使用MFC的情况

 1 #include <iostream>
 2 #include <afx.h>
 3 
 4 using namespace std;
 5 
 6 class CGraphics : public CObject
 7 {
 8     DECLARE_DYNAMIC(CGraphics)
 9 };
10 
11 class CLine : public CGraphics
12 {
13     DECLARE_DYNAMIC(CLine)
14 };
15 
16 class CRectangle : public CGraphics
17 {
18     DECLARE_DYNAMIC(CRectangle)
19 };
20 
21 IMPLEMENT_DYNAMIC(CRectangle, CGraphics)
22 IMPLEMENT_DYNAMIC(CLine, CGraphics)
23 IMPLEMENT_DYNAMIC(CGraphics, CObject)
24 
25 int main()
26 {
27     CRectangle *pRect = new CRectangle();
28     CLine *pLine = new CLine();
29 
30     cout << "pRect->IsKindOf(RUNTIME_CLASS(CGraphics)): " << pRect->IsKindOf(RUNTIME_CLASS(CGraphics)) <<endl; 
31 
32     cout << "pLine->IsKindOf(RUNTIME_CLASS(CGraphics)): " << pLine->IsKindOf(RUNTIME_CLASS(CGraphics)) <<endl; 
33 
34     cout << "pLine->IsKindOf(RUNTIME_CLASS(CRectangle)): " << pLine->IsKindOf(RUNTIME_CLASS(CRectangle)) <<endl; 
35 }

 

完整源码

https://git.oschina.net/zhujf21st/RTTIAppUsingMFC.git



 

posted @ 2016-07-05 19:15  jeffrey.chu  阅读(161)  评论(0编辑  收藏  举报

99code棋牌网