How to realize pseudo-reflection in C++!

Keywords: xml Java Programming

Bloggers encounter the problem of using XML to dynamically create class objects according to class names when writing programs. This approach is well implemented in languages with reflection mechanisms, such as JAVA, but C++ has no reflection mechanism. But powerful C++ allows us to achieve pseudo-reflection by ourselves.
The following is a C++ code written by the blogger himself to realize pseudo-reflection:
ClassFactory.h

#pragma once
#include <map>
#include <iostream>
#include <string>
using namespace std;

#define REGISTER(ClassName)                                             \
    ClassName* ObjectCreator##ClassName(){                              \
    return new ClassName;                                           \
}                                                                   \
    RegisterAction CreatorRegister##ClassName(                        \
#ClassName,(CreateObject)ObjectCreator##ClassName)

typedef void* (*CreateObject)(void); //Function pointer

class ClassFactory
{
private:  
    map<string, CreateObject> m_classMap ;  
    ClassFactory(){}; //Privatization of constructors

public:   
    void* GetClassByName(string className);  
    void RegistClass(string name, CreateObject method) ;  
    static ClassFactory& GetInstance() ;  
};


class RegisterAction
{
public:
    RegisterAction(string ClassName,CreateObject CreateOb)
    {
        ClassFactory::GetInstance().RegistClass(ClassName,CreateOb);
    }
};

ClassFactory.cpp

#include "ClassFactory.h"

void* ClassFactory::GetClassByName(string ClassName)
{  
    map<string, CreateObject>::const_iterator iter = m_classMap.find(ClassName);  
    if ( iter == m_classMap.end() )  
    {
        return NULL ; 
    } 
    else  
    {
        return iter->second() ;  
    }
}  

void ClassFactory::RegistClass(string name, CreateObject method)
{  
    m_classMap.insert(pair<string, CreateObject>(name, method)) ;  
}  

ClassFactory& ClassFactory::GetInstance()
{
    static ClassFactory sLo_factory;  
    return sLo_factory ;  
}  

In this way, pseudo-reflection is realized.
The following blogger takes you to analyze the code.
First, the blogger explains the idea of implementation for you. You can refer to the overall code above to see the local code below. The following code only releases statements to explain the idea. To know the implementation, please see the CLASS Factory. CPP above.

1. Write a class that has a private key-value pair of data to store the class name of the class object you need to create and the function pointer to create the class object. So we can dynamically create class objects according to class names!

class ClassFactory
{
private:  
    map<string, CreateObject> m_classMap ;  
    ClassFactory(){}; //Privatization of constructors
public:   
    void* GetClassByName(string className);  
    void RegistClass(string name, CreateObject method) ;  
    static ClassFactory& GetInstance() ;  
};

2. We need to write another class to store the class name of the class object you need to create and the function pointer to create the class object into the key pair.

class RegisterAction
{
public:
    RegisterAction(string ClassName,CreateObject CreateOb)
    {
        ClassFactory::GetInstance().RegistClass(ClassName,CreateOb);
    }
};

3. Because each class should have a function to create the class object, and a function pointer to the function, and add the class name of the class and the function pointer to the key pair. Repetition is a big taboo in programming, because every class has to do this, so bloggers abstract it and use macros to solve it.

#define REGISTER(ClassName)                                             \
    ClassName* ObjectCreator##ClassName(){                              \
    return new ClassName;                                           \
}                                                                   \
    RegisterAction CreatorRegister##ClassName(                        \
#ClassName,(CreateObject)ObjectCreator##ClassName)

typedef void* (*CreateObject)(void); //Function pointer

In this way, the explanation of thought is completed.
So how do you use library files written by bloggers?
All you need to do is add the blogger's lassFactory. h and lassFactory. CPP files to your project. Then write REGISTER (class name) after the declaration of the class that you need to create dynamically according to the class name, for example:

#pragma once
#include "CShape.h"
#include "ClassFactory.h"

class CTriangle : public CShape
{
public:
    CTriangle(){}
    virtual~CTriangle(){}
    virtual int Show();
};
REGISTER(CTriangle);

Then in practical application, we can dynamically create class objects by extracting class names from XML. The following code is shown: (The blogger uses the tinyXML2 parsing library here.)

"`
int ClassPrint()
{

list<CShape*> temp;

tinyxml2::XMLDocument doc;
if(doc.LoadFile("ClassXML.xml") != 0)
{
    cout << "Load XML File Failure" << endl;
    system("pause");
    exit(0);
}
tinyxml2::XMLElement* root = doc.RootElement();
tinyxml2::XMLElement* RSquare = root->FirstChildElement();
while(RSquare)
{
    CShape* PCShape = (CShape*)ClassFactory::GetInstance().GetClassByName(RSquare->GetText());
    if(PCShape != NULL)
    {
        temp.push_back(PCShape);
    }
    RSquare = RSquare->NextSiblingElement();
}
return 0;

}
Is it very simple? Give me a compliment if it's helpful. If you have any questions, you are welcome to criticize and correct them in the comments section.

Posted by kvnirvana on Thu, 30 May 2019 11:53:59 -0700