天天看点

C++ DynamicCreator 反射实现

C++反射实现

通过类的继承, 达到类的动态反射实现

#include <string>
#include <iostream>
#include <typeinfo>
#include <memory>
#include <unordered_map>
#include <cxxabi.h>

namespace neb
{

    class Actor
    {
    public:
        Actor(){std::cout << "Actor construct" << std::endl;}
        virtual ~Actor(){};
        virtual void Say()
        {
            std::cout << "Actor" << std::endl;
        }
    };

    template<typename ...Targs>
    class ActorFactory
    {
    public
        //typedef Actor* (*ActorCreateFunction)();
        //std::function< Actor*(Targs...args) > pp;

        static ActorFactory* Instance()
        {
            std::cout << "static ActorFactory* Instance()" << std::endl;
            if (nullptr == m_pActorFactory)
            {
                m_pActorFactory = new ActorFactory();
            }
            return(m_pActorFactory);
        }

        virtual ~ActorFactory(){};

        //Lambda: static std::string ReadTypeName(const char * name)

        //bool Regist(const std::string& strTypeName, ActorCreateFunction pFunc)
        //bool Regist(const std::string& strTypeName, std::function<Actor*()> pFunc)
        bool Regist(const std::string& strTypeName, std::function<Actor*(Targs&&... args)> pFunc)
        {
            std::cout << "bool ActorFactory::Regist(const std::string& strTypeName, std::function<Actor*(Targs... args)> pFunc)" << std::endl;
            if (nullptr == pFunc)
            {
                return(false);
            }
            std::string strRealTypeName = strTypeName;
            //[&strTypeName, &strRealTypeName]{int iPos = strTypeName.rfind(' '); strRealTypeName = std::move(strTypeName.substr(iPos+1, strTypeName.length() - (iPos + 1)));};

            bool bReg = m_mapCreateFunction.insert(std::make_pair(strRealTypeName, pFunc)).second;
            std::cout << "m_mapCreateFunction.size() =" << m_mapCreateFunction.size() << std::endl;
            return(bReg);
        }

        Actor* Create(const std::string& strTypeName, Targs&&... args)
        {
            std::cout << "Actor* ActorFactory::Create(const std::string& strTypeName, Targs... args)" << std::endl;
            auto iter = m_mapCreateFunction.find(strTypeName);
            if (iter == m_mapCreateFunction.end())
            {
                return(nullptr);
            }
            else
            {
                //return(iter->second());
                return(iter->second(std::forward<Targs>(args)...));
            }
        }

    private:
        ActorFactory(){std::cout << "ActorFactory construct" << std::endl;};
        static ActorFactory<Targs...>* m_pActorFactory;
        std::unordered_map<std::string, std::function<Actor*(Targs&&...)> > m_mapCreateFunction;
    };

    template<typename ...Targs>
    ActorFactory<Targs...>* ActorFactory<Targs...>::m_pActorFactory = nullptr;

    template<typename T, typename ...Targs>
    class DynamicCreator
    {
    public:
        struct Register
        {
            Register()
            {
                std::cout << "DynamicCreator.Register construct" << std::endl;
                char* szDemangleName = nullptr;
                std::string strTypeName;
#ifdef __GNUC__
                szDemangleName = abi::__cxa_demangle(typeid(T).name(), nullptr, nullptr, nullptr);
#else
                //in this format?:     szDemangleName =  typeid(T).name();
            szDemangleName = abi::__cxa_demangle(typeid(T).name(), nullptr, nullptr, nullptr);
#endif
				std::cout<<szDemangleName<<std::endl;
                if (nullptr != szDemangleName)
                {
                    strTypeName = szDemangleName;
                    free(szDemangleName);
                }

                ActorFactory<Targs...>::Instance()->Regist(strTypeName, CreateObject);
            }
            inline void do_nothing()const { };
        };
        DynamicCreator()
        {
            std::cout << "DynamicCreator construct" << std::endl;
            m_oRegister.do_nothing();
        }
        virtual ~DynamicCreator(){m_oRegister.do_nothing();};

        static T* CreateObject(Targs&&... args)
        {
            std::cout << "static Actor* DynamicCreator::CreateObject(Targs... args)" << std::endl;
            return new T(std::forward<Targs>(args)...);
        }

        virtual void Say()
        {
            std::cout << "DynamicCreator say" << std::endl;
        }
        static Register m_oRegister;
    };

    template<typename T, typename ...Targs>
    typename DynamicCreator<T, Targs...>::Register DynamicCreator<T, Targs...>::m_oRegister;

    class Cmd: public Actor, public DynamicCreator<Cmd>
    {
    public:
        Cmd(){std::cout << "Create Cmd " << std::endl;}
        virtual void Say()
        {
            std::cout << "I am Cmd" << std::endl;
        }
    };

    class Step: public Actor, DynamicCreator<Step, std::string, int>
    {
    public:
        Step(const std::string& strType, int iSeq){std::cout << "Create Step " << strType << " with seq " << iSeq << std::endl;}
        virtual void Say()
        {
            std::cout << "I am Step" << std::endl;
        }
    };

    class Worker
    {
    public:
        template<typename ...Targs>
        Actor* CreateActor(const std::string& strTypeName, Targs&&... args)
        {
            Actor* p = ActorFactory<Targs...>::Instance()->Create(strTypeName, std::forward<Targs>(args)...);
            return(p);
        }
    };
}
           
C++ DynamicCreator 反射实现

根据流程图可以看到,所有的XXXActor都继承Actor和DynamicCreator, 在程序运行初始阶段,main函数运行之前

  1. 构造XXXActor,会先构造父类DynamicCreator, 调用register_.doNothing(), 从而调用egister构造函数, 于是将XXXActor的类名称,以及参数列表,以及DynamicCreator::CreateObject函数保存到 ProcessorFactory::m_mapCreateFunction
  1. main函数之后, 通过Actor* CreateActor(const std::string& strTypeName, Targs&&… args)构建类实例,将类的全名称以及参数通过改方法传进来,进一步构建实例,最终调用ActorFactory ::Create 遍历m_mapCreateFunction, 依次创建所有Actor子类实例

综上来看, 在实际的运行过程中, 可以根据配置文件,动态的构建类的实例。如果设备从刚开始要考虑到数据不同场景下的处理方式, 可以动态创建, 接下来, 我们从写一个简单的main函数来看看具体的输出

int main() {
    std::cout<<"+++++++++ in main function()+++++++++"<<std::endl;
    std::cout<<"hello there"<<std::endl;
    neb::Worker W;
    neb::Actor* p1 = W.CreateActor(std::string("neb::Cmd"));
    p1->Say();
    //std::cout << abi::__cxa_demangle(typeid(Worker).name(), nullptr, nullptr, nullptr) << std::endl;
    std::cout << "################" << std::endl;
    neb::Actor* p2 = W.CreateActor(std::string("neb::Step"), std::string("neb::Step"), 1002);
    p2->Say();
    return 0;
}
           
DynamicCreator Register construct
neb::Cmd
construct ActorFactory Instance
ActorFactory construct
bool ActorFactory::Regist(const std::string& strTypeName, std::function<Actor*(Targs... args)> pFunc)
m_mapCreateFunction.size() =1
DynamicCreator Register construct
neb::Step
construct ActorFactory Instance
ActorFactory construct
bool ActorFactory::Regist(const std::string& strTypeName, std::function<Actor*(Targs... args)> pFunc)
m_mapCreateFunction.size() =1


+++++++++ in main function()+++++++++
hello there
construct ActorFactory Instance
Actor* ActorFactory::Create(const std::string& strTypeName, Targs... args)
static Actor* DynamicCreator::CreateObject(Targs... args)
Actor construct
DynamicCreator construct
Create Cmd 
I am Cmd
################
construct ActorFactory Instance
Actor* ActorFactory::Create(const std::string& strTypeName, Targs... args)
static Actor* DynamicCreator::CreateObject(Targs... args)
Actor construct
DynamicCreator construct
Create Step neb::Step with seq 1002
I am Step
           

从输出结果可以看到, 在main函数之前, 就调用了两次的DynamicCreator Register construct, cmd和Step两个类将类名已经注册,main函数之后, 通过W传入类名, 和类参数构建两个类的实例, 反射到此就已经实现了,可以通过类名方便的实现了

继续阅读