Runtime class information)

Source: Internet
Author: User

When I first started learning MFC, I came across something about runtime class info. I can know at runtime what type the pointer of an object is. at that time, I didn't study it in depth, and I didn't use much. I just thought it was amazing. during the development of this engine, I gradually felt that this was a good thing. I have implemented a system like this in the engine, which is quite handy. Here I will introduce it.
Basically, this runtime class Information System (rtcis for the moment) has the following functions:
*. The most important thing is to provide a unified memory distributor for classes that use rtcis. all instances of this class are allocated from this pool, because the memory distributor is for a single type of data, it is relatively simple and efficient to write (using templates), and, you can use the class name to identify the memory allocation pool, which facilitates the memory pool to output some debugging information.
*. Because instances of this class are allocated in a unified memory pool, you can quickly enumerate all instances of this class, which is sometimes useful.
*. You can create a class object at runtime based on the class name (a string ).
*. You can determine the type of an object at runtime.

This system is mainly implemented by adding static variable methods to a class. The following describes a set of lite implementations. The implementations in the engine are more complex, including some other functions, for example, the Inheritance Information of the record class, the instance of the enumeration class, assign an ID for each class, and create an instance based on this ID. All these functions can be found in Code Is not listed.
* First, define the base class of a class information: cClass
Class cClass
{
Public:
Virtual void * New () = 0;
Virtual void Delete (void *) = 0;
Const char * getname () {return _ classname. c_str ();}
Static void * newbyname (const char * clssname)
{
Return _ classes [STD: string (clssname)]-> New ();
}
Protected:
Void setname (const char * name)
{
_ Classname = Name;
_ Classes [_ classname] = This; // register yourself to the global class information table.
}
STD: String _ classname; // Class Name
Static STD: Map <STD: String, cClass *> _ classes; // global class information table
};
*. Then define a macro: declare_class () to declare rtcis in the class ,(
For clarity, \ )
# Define declare_class (clss)
Public:
// Class information, derived from the base class cClass
Class cClass _ # clss: Public cClass
{
Public:
Virtual void * New () {return _ pool. alloc ();}
Virtual void Delete (void * P) {_ pool. Free (clss *) P );}
Cmempool <clss> _ pool; // memory pool of this class
};
Static cClass _ # clss * _ instantiate ()
{
Static cClass _ # clss instance;
Instance. setname (# clss); // set the class name and register it in the global class information table.
Return & instance;
}
CClass * getclass () {return _ class ;}
Static cClass _ # clss * _ class; // static variable
*. Then define a macro to implement rtcis:
# Define implement_class (clss)
Clss: cClass _ # clss * clss: _ class = clss: _ instantiate (); // define and initialize static variables

*. define several macros to facilitate the use of this system:
# define class_new (clss) (clss *) (clss: _ class-> New ())
# define class_delete (p)-> getclass ()-> Delete (p)
# define class_newbyname (clssname) cClass: newbyname (clssname)
# define class_getname (p)-> getclass ()-> getname ()
*. the following is an example about fruit:
in the header file:
class cfruit
{< br> Public:
virtual cClass * getclass () = 0;
//...
//...
};
class capple: Public cfruit
{< br> Public:
declare_class (capple);
//...
//...
};
class corange: Public cfruit
{< br> Public:
declare_class (corange);
//...
//...
};
class cgrape: Public cfruit
{< br> Public:
declare_class (cgrape);
//...
//...
};

In the CPP file:
Implement_class (capple );
Implement_class (corange );
Implement_class (cgrape );
Actual use:
Int main ()
{
Cfruit * fruit1 = class_new (capple );
Cfruit * fruit2 = class_new (corange );
Cfruit * fruit3 = class_newbyname ("cgrape ");
Assert (STD: string ("capple") = class_getname (fruit1 ));
Assert (STD: string ("corange") = class_getname (fruit2 ));
Assert (STD: string ("cgrape") = class_getname (fruit3 ));

Class_delete (fruit1 );
Class_delete (fruit2 );
Class_delete (fruit3 );
}

In addition, Havok's physical engine has been viewed over the past two days, and its object allocation adopts a similar method, and a better feature is for a class, it can be configured with an independent memory distributor in each thread (this can avoid locking in the memory allocation code and help improve efficiency), such

Void thread1 ()
{
Cfruit * fruit1 = class_new (capple );
Class_delete (fruit1 );
}

Void thread2 ()
{
Cfruit * fruit2 = class_new (capple );
Class_delete (fruit2 );
}
Fruit1 and fruit2 are automatically allocated from two independent memory pools. I haven't seen how Havok is implemented yet, but it should not be too troublesome. I hope I will have time to add this feature in the future.

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.