Rtti in MFC (runtime type identification, runtime types identification) in detail (refer to "In Layman's MFC")

Source: Internet
Author: User

The implementation of Rtti in MFC is mainly achieved by using a structure called CRuntimeClass to link the information of each "related class". In a nutshell, it is the creation of CRuntimeClass static variables within a class that requires the use of RTTI technology to store information about the class (including the class name, pointers to the cruntimeclass structure of the base class, and the "related class" information to form the next pointer to the list, and information such as the first pointer (static) of the list, where "relational" refers to the relationship between all classes inherited from the same base class. The link process for these information (CRuntimeClass) nodes is simplified as follows:

(Note: The variable name of the CRuntimeClass of a class (such as CObject) is the class name (for example: CLASSCOBEJCT))

1. When building a base class using RTTI technology, create a new information link list.

Figure 1

When creating a new base class that requires RTTI technology, we need to create a cruntimeclass structure like Figure 1, which actually initializes the list of information that manages all of the classes that are "related" to that class, where The static variable pfirstclass of CRuntimeClass is the first node of the information list.

2. When a subclass is created, the subclass information (the CRuntimeClass structure of the subclass) is associated to the Information link list. (CCmdTarget inherited from CObject)


Figure 2


The information for the subclass is also added to the linked list, when the Pfirstclass pointer points to the new information. The simulation code is as follows

Ccmdtarget::classccmdtarget.next = CRuntimeClass::p firstclass; CRuntimeClass::p firstclass = pccmdtarget::classccmdtarget;

3. The new subclass is similar in the following case, directly.

a) CWinThread inherits from CCmdTarget and joins its information node (Classcwinthread) in the linked list.

Figure 3


B) CWnd inherits from CCmdTarget, and its information node (CWND::CLASSCWND) is added to the Information link list.


Figure 4



It is because of the existence of such a list that the "related classes" information (CRuntimeClass structure) is associated, so we can easily implement the relevant functions of rtti.

RTTI provides the following two very useful features:
(1) The actual type referred to by the query pointer and reference.
(2) Safely convert a pointer or reference of a base class type to a pointer or reference of a derived type.

Know the macro control, let us carefully solve the planing, MFC in the details of how to implement RTTI technology.

First, let's take a look at how each information node is defined.

As mentioned earlier, each class that uses Rtti in MFC creates a CRuntimeClass object to store the information of the object, and the "somewhat related class" is associated with a linked list formed by this structure. In Houtie (Hou Junjie), in the "in-depth MFC (second Edition)", this simulation of the structure (CRuntimeClass).

struct cruntimeclass{      LPCSTR m_lpszclassname;//The name of the class that contains the CRuntimeClass object.      int m_nobjectsize;//m_lpszclassname The number      of bytes occupied UINT M_wschema;  Category number      cobject* (pascal* m_pfncreateobject) ();//null = abstract class, a pointer to the constructor of the class containing the struct object      cruntimeclass* M_pbaseclass; The CRuntimeClass object pointer to the base class of the class that contains the struct object             //The following is the variable that is required to make up the linked list      static cruntimeclass* Pfirstclass;//The first node      of the list Cruntimeclass* M_pnextclass; The next node of the node. }


We know that in MFC to use the RTTI, will always use the Declare_dynamic/implement_dynamic macro, it is this pair of macros, link "related classes" linked list. Since it is said to be a "pair", of course, is to be used, one for the declaration, one for the definition, you pick firewood to my weaving, husband and wife both home also. = =!

Before we discuss the source code, we need to know that the macro definition uses # To change the macro parameter to a string with # #把两个宏参数贴合在一起.

Such as

#include <iostream>using namespace std; #define TEST (X) #Xint main () {cout << Test (test) << Endl;}
Output:


Figure 5

Again like,

#include <iostream>using namespace std; #define TEST (X, Y)  x# #Yint Main () {cout << Test ("x#", "#Y") <& Lt Endl;}

Output:

Figure 6

Well, with a series of discussions above, now let's concentrate on the analysis of how the Rtti in MFC is implemented. +_-!

The first is the declaration, the declared macro declare_dynamic is defined as follows:

#define  declare_dynamic (class_name) public:static CRuntimeClass class# #classname; Virtual cruntimeclass* Getruntimeclass () const;

As mentioned earlier, to use the RTTI must create a static CRuntimeClass structure object, from this declared macro, we can know that a CRuntimeClass object named Class+ class name is defined, and a virtual function that goes back to the address of the object. The reason is a virtual function because the subclass and the parent class return a different CRuntimeClass.


Next is the implementation of macro implement_dynamic, this macro a little bit messy, please seriously read, really do not understand the words, it doesn't matter, the code behind I have a detailed interpretation. Hey...... Gossip less, on the code.

#define  implement_dynamic (class_name, Base_class_name) _implement_runtimeclass (class_name, Base_class_name, 0xFFFF, NULL) #define _IMPLEMENT_RUNTIMECLASS (class_name, Base_class_name, Wschema, pfnnew) static char _lpsz# #class_ Name[] = #class_name; CRuntimeClass class_name::class# #class_name = {_lpsz# #class_name, sizeof (class_name), Wschema, Pfnnew, Runtime_class ( base_class_name), NULL}; Static Afx_classinit _init_# #class_name (&class_name::class# #class_name); cruntimeclass* class_name::getruntimeclass () const         {return &class_name::class# #class_name;} #define RUNTIME_CLASS (class_name)  (&class_name::class# #class_name)

What do you think? Did you get scared? If you say no, then recommend you directly to see the source of the MFC section.

The first two lines of code, the equivalent of rescue, this nothing to say, understand the macro definition, all understand!

The _implement_runtimeclass macro, in effect, completes the CRuntimeClass variable class# #class_name的初始化 to the DECLARE_DYNAMIC macro declaration, as well as the Getruntimeclass () The definition of the function. Here is the part of the code that is intercepted.

static char _lpsz# #class_name [] = #class_name;      Gets the name of the class that contains the CRuntimeClass cruntimeclass class_name::class# #class_name = {\/    /Initialize the CRuntimeClass parameter _lpsz# #class_ Name, sizeof (class_name), Wschema, pfnnew, \  runtime_class (base_class_name), NULL}; \  
The AFX_CLASSINIT structure is used in the _implement_runtimeclass macro to initialize the CRuntimeClass so that it has a linked list of classes. Afx_classinit its constructor implements a #class_name进行操作 to the CRuntimeClass object class#.

struct Afx_classinit{afx_classinit (cruntimeclass* pnewclass) {pnewclass->m_pnextclass = CRuntimeClass:: Pfirstclass; CRuntimeClass::p firstclass = Pnewclass;}};
Although it may not be clear, but that is probably the meaning. It's the last example.

In the header file, we declare it with declare_dynamic.

In *.h file.class cwnd:public Ccmdtarget{public:cwnd () {}~cwnd () {}declare_dynamic (CWnd)/* above Declare_dynamic (CWnd) , unfold becomes: public:static CRuntimeClass Classcwnd; Declare static variables virtual cruntimeclass* getruntimeclass () const;*/};
In the source file, we use implement_dynamic to implement.

In *.cpp fileimplement_dynamic (CWnd, CCmdTarget)/*implement_dynamic (CWnd, CCmdTarget), expand to become: Static char _lpszcwnd[ ] = "CWnd";//define and initialize static variables Classcwndcruntimeclass Classcwnd = {_lpszcwnd, sizeof (CWND), 0xFFFF, NULL,                        &ccmdtarget: : Classccmdtarget, NULL}//defines and initializes a static variable _init_cwnd, actually calls its constructor and connects Classcwnd to the linked list. Static Afx_classinit _init_cwnd (&cwnd::classcwnd);//Get CRuntimeClass object Classcwnd pointer cruntimeclass* CWnd:: Getruntimeclass () Const{return &cwnd::classcwnd;} */


OK, I believe insist on seeing the small partners here has probably understood the MFC about RTTI the most important two macros it? There are a lot of things to discuss about MFC's RTTI, and if there is time, I will continue to update the relevant content. \ (^o^)/~, all right, here's the last word:



"References"

1. Houtie-in-depth MFC (second edition)

2. MSDN Related content



Rtti in MFC (runtime type identification, runtime types identification) in detail (refer to "In Layman's MFC")

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.