MFC principle Third speaking. Rtti run-Time type identification

Source: Internet
Author: User
MFC principle Third speaking. RTTI Runtime type identification what is Rtti

RTTI. Identification of the type at run time. The run-time type information program. Ability to use a base class (parent class) pointer or reference to examine these pointers or refer to the objects they refer to. The actual derived type

In simple terms, the parent class pointer is used to check which class the object belongs to.

1. Questions to be clarified in this blog post

1.1 Why does MFC want to build Rtti

1.2 Declare_dynamic macro

1.3 IMPLEMENT_DYNAMIC macro

1.4 RUNTIME_CLASS macro

1.5 Cruntime Class Structural body

2. Simple to understand the use of keywords

1. The role of static variables defined in the class and how to initialize them.

2. The function of the const variable defined in the class and how to initialize it

3. The function of the variable defined by the static + const in the class and how to initialize it.

Second, C + + simple Rtti operation type identification

When it comes to explaining what we need to know. Write a simple small example. Use the C + + self-rtti program at compile time. Note that is at compile time.

Specific practices:

1. To use the typeID keyword typeid (object) typeID (class name)

2. First to include the header file <typeinfo.h>

3. Start the C + + own type. Properties, configuration Properties, C + +, language-enabled run-time type information command line Plus, we can just add/gr.

For example:

  

1. First we create two classes. One is Cdog one is ccat.

2. Our main function then defines the Cdog object and the Ccat object. and determine whether the Cdog object belongs to the Cdog class.

3. Print if it belongs to us. otherwise.

Specific code:

  

#include <stdio.h>#include<typeinfo.h>#include"Dog.h"#include"Cat.h"intMainintargcChar*argv[])    {Cdog Dog;    Ccat Cat; if(typeID (dog) = =typeid (Cdog)) to determine whether the dog object belongs to the Cdog class is basically this line of code {printf ("It belongs to this object \ r \ n"); }    Else{printf ("This is not the object. \ r \ n"); } System ("Pause");}

Implementing the Application:

  

This is the simple rtti run-time type recognition.

The Static keyword in the class. The const keyword static + const keyword function and initialization

1.static keyword-modified variable. External initialization. And is not dependent on the object. That is, the direct class name:: Variable can call the type class Name:: member variable = value;

2.const keyword-Modified variables can only be read and cannot be changed. Initialization must be initialized in the initialization list of the class's construction.

3.static + Const-Modified variable. Can only read can not change.  The class name is called directly. Initialize in the external initialization of the Const type class Name:: member variable = value;

Iv. Why MFC builds Rtti itself

MFC because it appeared earlier. So I realized the rtti. and relies on two macros.

1.2 of Declare_dynamic macros

1.3 of IMPLEMENT_DYNAMIC macros

1.3 of these macros also contain a key macro runtime_class and key structure Cruntime CLASS

One, use 1.2 macros 1.3 macros.

Now we want our own class to have Rtti runtime type recognition.

Steps:

1. Our own WinApp class defines the DECLARE_DYNAMIC macro

2.main function before using IMPLEMENT_DYNAMIC macro

3. Use ISKINDOF (Cruntime class *) to determine if the parent class is inherited. Because it's cruntime class * So we're going to use a macro containing our parent class Runtime_class (parent Class)

4. Returns 1 if the parent class is inherited. otherwise returns 0

Know the steps. Then open the code for the first blog. Implement the window program yourself. To write.

1. Define declare_dynamic macros within your own class:

    

2. Define IMPLEMENT_DYNAMIC (own class name, parent class name) in the implementation file of your own class

3. Own class already has the Rtti type recognition. Use Rtii to run the recognition.

Two, RUNTIME_CLASS macro analysis

Above we use the RUNTIME_CLASS macro to do the use then we look at how MFC defines.

#define _runtime_class (class_name) ((cruntimeclass*) (&class_name::class# #class_name))

It's actually a macro. But we can disassemble it.

  

#define _runtime_class (CWINAPP) ((cruntimeclass*) (&cwinapp::classcwinapp))

Where # #代表了链接的意思 is class# #ClassName can become Classwinapp

So the above code we write with the macro can be replaced by our parsed macros.

Returned a cruntime Class *. Returns the address of a member inside a CWinApp. Because there is a fetch address symbol in front of it.

First look at the CRuntimeClass structure.

Three, CRuntimeClass structural body
structcruntimeclass{//AttributesLPCSTR m_lpszClassName; Class nameintm_nobjectsize;                      The size of the class UINT M_wschema; The number of the load class CObject* (pascal* m_pfnCreateObject) ();//NULL = abstract class#ifdef _afxdll CRuntimeClass* (pascal*M_pfngetbaseclass) ();#elseCRuntimeClass*M_pbaseclass;#endif//Operationscobject*CreateObject (); BOOL Isderivedfrom (Constcruntimeclass* Pbaseclass)Const; Judging function//Dynamic name lookup and creation    Staticcruntimeclass*PASCAL fromname (LPCSTR lpszclassname); Staticcruntimeclass*PASCAL fromname (lpcwstr lpszclassname); Staticcobject*PASCAL CreateObject (LPCSTR lpszClassName); Staticcobject*PASCAL CreateObject (Lpcwstr lpszClassName);//Implementation    voidStore (carchive& ar)Const; Staticcruntimeclass* PASCAL Load (carchive& ar, uint*pwschemanum); //CRuntimeClass objects linked together in simple listCruntimeclass* M_pnextclass;//Hold down a cruntimeclass    Constafx_classinit*M_pclassinit;};

Because there are more members. Simplify it below.

  

struct cruntimeclass{//  Attributes    LPCSTR m_lpszclassname;           Class name     int  m_nobjectsize;                      The size of the class    UINT M_wschema;                      The number    of the load class ... BOOL Isderivedfrom (constconst;  Determine if the function is a parent class ...    CRuntimeClass* M_PNEXTCLASS;       // Hold down a cruntimeclass     };

This is a linked list. is a structure of the record type. Because it is a linked list, so it can be checked.

Four, DECLARE_DYNAMIC macro analysis

In fact, declare_dynamic macro is also a word replacement of things. We can look at the code.

#define Declare_dynamic (class_name) \ Public: \    staticconstclass# # class_name; \    virtualconst; \ Replace with the code below.  Public :      Static Const CRuntimeClass Classcmyapp;      Virtual Const

The macros in our CMyApp can be removed directly.

Do things;

1. The static const global readable variable is declared. That is, the structure of a type record information structure body CRuntimeClass

Question: Since it is static const definition. Then it must be initialized outside. That's our

Implement_dynamic macros. And this macro also contains macros inside. And we added default parameters.

#define Implement_runtimeclass (Class_name, Base_class_name, Wschema, pfnnew, class_init) \    const CRuntimeClass class_name::class# #class_name = {\        sizeof(class  Class_ Name), Wschema, pfnnew, \            runtime_class (base_class_name), NULL, class_init}; \    CRuntimeClassconst  \        return runtime_class (class_name);}

Let's make it a bit simpler. In fact, it is also a word replacement game.

Const CRuntimeClass Cmyapp::classcmyapp = {        "cmyapp"sizeof(class  CMyApp), NULL, NULL,         runtime_class (CWINAPP), NULL, NULL}; CRuntimeClassconst  {     return  runtime_class (CMyApp);}

is actually initializing our static + const variable.

There's a runtime_class inside of us because we've parsed the runtime_class. It's actually getting Cwinapp::classcwinapp members.

So you can continue with the replacement.

Replace the following.

  

Const CRuntimeClass Cmyapp::classcmyapp = {        "cmyapp"sizeof(class  CMyApp), NULL, NULL,         (CRuntimeClass*) (&Cwinapp::classcwinapp), NULL, NULL}; CRuntimeClassconst  {     return(cruntimeclass*) (&CMyApp:: Classcwinapp);}

Code:

  

Our implement_dynamic macro is equivalent to the following code.

1. Initialize the members of the CRuntimeClass structure inside the class.

2. Added a member of the Classcwinapp that gets the parent class.

V. RTTI Summary

According to section fourth. We have restored all the macros themselves. Look at the clutter. But it's easy to summarize.

1. First, there is a structure called CRuntimeClass. The type description is stored inside. such as the class name. Size. and determine if the parent class ....

2. There is a macro called DECLARE_DYNAMIC macro. This macro is defined as a member of a CRUNTIMECLASS structure of its own. And added a virtual function that gets its own member.

3. Implementing a macro implement_dynamic is actually initializing the CRuntimeClass member defined in the declare_dynamic. and implements the virtual function that obtains the member itself.

Six, Rtti method analysis of type recognition in run time

Above we have a summary of Rtti and CRuntimeClass and two macros. Then we need to use ISKINDOF to use it. So, how does this function work?

1. Take out our own Classcmywinapp pointer to the current object.

2. Loop traversal is equal to parent class

3. Does not equal the parent class to traverse. Because CRuntimeClass is a linked list structure. Always traverse. Address comparison. Returns True if yes

Because the code is more troublesome than teaching. So directly affixed inside the approved code.

    

BOOL CObject::IsKindOf (Constcruntimeclass* PClass)Const{    .... CRuntimeClass* Pclassthis =Getruntimeclass (); Get your own CRuntimeClass members ...returnPclassthis->Isderivedfrom (PClass); Make a judgment.} BOOL Cruntimeclass::isderivedfrom (Constcruntimeclass* Pbaseclass)Const{The remaining code is omittedConstcruntimeclass* Pclassthis = This; Get the CRuntimeClass member of the byte while(Pclassthis! =null) loop traversal is not NULL {if(Pclassthis = =pbaseclass) Returns True if it is a parent classreturnTRUE; Pclassthis= pclassthis->M_pbaseclass; Otherwise equals the parent class pointer. Continue traversal judgment}returnFALSE;//no return False}
Vii. write code to print out the parent class information. And the Inheritance relationship

Since our own class has a pointer to CRuntimeClass * stored inside. And it's a linked list. Its parent class also has its own. Then it is perfectly possible to traverse. Prints out the information for the parent class.

Implementation ideas:

1. Get your own CRuntimeClass * pointer

2. Traversing the CRuntimeClass member is null

3. Print out the contents of the struct in sequence, not NULL

4. The current CRuntimeClass pointer is modified to the CRuntimeClass * pointer of the parent class

Specific code implementation:

  

voidCMyApp::P rintparentruntimeinfo () {//1. Get your current CRuntimeClass information. Traverse.CRuntimeClass *pcurclass =Getruntimeclass (); //to cycleCString str;  while(NULL! =Pcurclass) {STR=""; Str. Format (TEXT ("the name of the class =%s \ r \ n"), pcurclass->m_lpszclassname);//the name of the classOutputDebugString (str); STR=""; Str. Format (TEXT ("the size of the class =%d \ r \ n"),pcurclass->m_nobjectsize);        OutputDebugString (str); STR=""; Str. Format (TEXT ("the class number%d \ r \ n"), pcurclass->M_wschema);        OutputDebugString (str); STR=""; Str. Format (TEXT ("the parent class pointer%p \ r \ n"), pcurclass->M_pbaseclass);        OutputDebugString (str); if(Pcurclass->m_pbaseclass! =nullptr) {STR=""; Str. Format (TEXT ("class's parent class name%s \ r \ n"), pcurclass->m_pbaseclass->m_lpszclassname);        OutputDebugString (str); } STR= TEXT ("--------------------------------\ r \ n");        OutputDebugString (str); Pcurclass= pcurclass->m_pbaseclass;//always traverse to the top-level position    }}

Within the ininstance, you can call.

Implementation result: Use DebugView to get information.

Classroom code: Link: pan.baidu.com/s/1wp6ptwssr8qozo0t3vnzyq Password: 2y2o

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.