Foreword: Like the same above, this article is from the question of another friend (see post http://community.9cbs.net/expert/topic/3202/3202729.xml?temp=5.602664e-02)
C is not a dynamic language, so it is possible to achieve dynamic creation of classes from the language mechanism, but such demand may exist, a similar example is the Create method of the CWnd class in the MFC, its first parameter is Window Class Name, this allows users to create the corresponding window through the name of Class.
To achieve this, there must be a "management center" for the name of the registration class, and can call a method through the name to create the corresponding class. Combine the design idea of the class factory, here we let the base class in the inheritance system as a "management center", which maintained the necessary information of all derived classes, including class names and factory functions, these two must establish mapping relationships, MAP is a good choice. After defining a derived class, it will automatically register with the base class, but how to automatically? Let's take a look at the program first:
/ / For the convenience of writing, the following code is in the .cpp file
#ifDef _MSC_VER
#pragma
WARNING (Disable: 4786)
#ENDIF
#include
#include
Using
Namespace
STD;
Class Base
{
PUBLIC:
Virtual
Void print ()
// Test
{
Cout <<
"This is base" << ENDL;
}
protected:
TYPEDEF BASE * (* ClassGen) ();
// Declaration function pointer
Static
Void
Register (const)
Char * class_name, Classgen Class_Gen
// Registration function
{
Class_set.insert (Map Char *, classgen> :: value_type (class_name, class_gen); } PUBLIC: Static Base * Create (Const Char * class_name) // Factory function { Map Char *, Classgen> :: item; IF (item_set.Find (class_name))! = class_set.end ()) { Return ((* iter). Second) (); } Return NULL; } protected: Static Map CHAR *, CLASSGEN> CLASS_SET; // Storage subclass information } Map CHAR *, BASE :: Classgen> Base :: Class_Set // Static member variable definition Class Derived: Public Base { PUBLIC: Struct DerivedRegister // Auxiliary class for registration { DerivedRegister () { // Register the subclass, although Map can guarantee unique, but still register once Static Bool bregistered = False; IF (! BREGISTERED) { Base :: REGISTER "Derived", Derived :: Create); // Register subclass information Bregistered = true; } } } static base * create () // Factory function { Return New deerid; } PUBLIC: Virtual Void print () // Test { Cout << "This is deive" << Endl; } } Static Derived :: DeriveDregister Derived_for_registering; // There is no other mechanism to ensure that the registration function is called in the global space. / / Must not have, define a global variable to complete this glorious task, it looks a bit int main () { Base * Pderived = Base :: CREATE "Derived"); // Class name can be dynamically entered IF (Pderived) Pderived-> Print (); // Create a successful call virtual function Else Cout << "Crete error" << endl; SYSTEM "PAUSE"); Return 0; } This is true, some friends may feel very troublesome, in fact, we will use the macro definition to transform it, it will be very beautiful, the code will see it. Still talk about the automatic registration function, first, why do you want to automatically register? This is to maximize the implementation, actually use manual registration, but we have to call each class's registration function one by one in the main function. So how do we realize automatic registration? The method is to place the registration code into a buffer-auxiliary class constructor, then define a static global variable of such a class, so that the constructor is called, :), the disadvantage is more than an additional object, except for the registration It doesn't use it, and I didn't use the auxiliary class, but directly registered in the constructor of the derived class, and then define the global variables of the school, which clearly wasts space, and uses the auxiliary class to reduce the minimum overhead. ). Let us look at the way to use the macro: #ifDef _MSC_VER #pragma WARNING (Disable: 4786) #ENDIF #include #include Using Namespace STD; // Used to declare the base class with dynamic creation function #define declare_dyncrt_base (base) / PUBLIC: / TYPEDEF BASE * (* ClassGen) (); / Static Void Register (const) Char * class_name, classgen class_gen / {/ Class_set.insert (Map Char *, classgen> :: value_type (class_name, class_gen); / } / PUBLIC: / Static Base * Create (Const Char * class_name) / {/ Map Char *, Classgen> :: item; / IF ((iter = class_set.find (class_name))! = Class_Set.end ()) / {/ Return ((* iter). Second (); / } / Return NULL; / } / protected: / Static Map Char *, classgen> class_set; // is used to implement the base class #define import_dyncrt_base (base) / Map CHAR *, BASE :: Classgen> Base :: Class_Set; // Used to declare a class that can be created dynamically #define declare_dyncrt_class (derived, base) / PUBLIC: / Struct Derived ## register / {/ Derived ## register () / {/ Static Bool bregistered = False; / IF (! BREGISTERED) / {/ Base :: Register (#derived, crete); / BREGISTERED = True; / } / } / }; / static base * create () / {/ Return New deerive; / } // Used to implement a class that can be created dynamically #define import_dyncrt_class (derived) / Static Derived :: Derived ## register derived ## _ for_registering; // Test Class Base { Declare_Dyncrt_base (base) // Declare the dynamic base class Declare_DyncRT_Class (Base, Base) // The base class can also create itself PUBLIC: Virtual Void print () { Cout << "This is base" << ENDL; } } Implement_dyncrt_base (base) // Realize the dynamic base class Implement_dyncrt_class (base) // Realize dynamic class Class Derived: Public Base { Declare_Dyncrt_class (derived, base) // Declaration Dynamic Class PUBLIC: Virtual Void print () { Cout << "This is deive" << Endl; } } Implement_dyncrt_class (derived) // Realize dynamic class int main () { Base * PBase = Base :: Create "Base"); // Class name can be dynamically entered IF (PBASE) PBase-> Print (); // Create a successful call virtual function Else Cout << "CREATE BASE ERROR" << ENDL; Base * Pderived = Base :: CREATE "Derived"); // Class name can be dynamically entered IF (Pderived) Pderived-> Print (); // Create a successful call virtual function Else Cout << "CREATE DERIVED ERROR" << ENDL; SYSTEM "PAUSE"); Return 0; } The above macro definition can be reused (if it is a bit of recognition, it is a similar macro when it is supported by serialization and dynamic creation, etc., when using, simply use these four macros, You can realize dynamic creation, it feels good, but reminds you that two of them should be placed in .cpp files. This method still has some shortcomings, but this paper mainly provides a thinking, which can be changed according to the specific situation. (FreefalCon at 2004.09.19)