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);
}
};
}
根据流程图可以看到,所有的XXXActor都继承Actor和DynamicCreator, 在程序运行初始阶段,main函数运行之前
- 构造XXXActor,会先构造父类DynamicCreator, 调用register_.doNothing(), 从而调用egister构造函数, 于是将XXXActor的类名称,以及参数列表,以及DynamicCreator::CreateObject函数保存到 ProcessorFactory::m_mapCreateFunction
std::unordered_map<std::string, std::function<Actor*(Targs&&...)> > m_mapCreateFunction;
- 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传入类名, 和类参数构建两个类的实例, 反射到此就已经实现了,可以通过类名方便的实现了