C++实现类似java反射的功能

用过java的开发者都知道,java有一种叫做反射的功能,可以根据类名来生成类的实例,这种机制的好处就是可以在不修改代码的情况下,可以通过配制文件来决定生成什么类的对像。那么对于使用C++开的人来说,有没有一种方式实现类似的功能呢?

虽然C++没有从语言层面提供反射的机制,但是还是可以简单的模拟出类似的功能的。在查找了很多资料,也看过很多人写的不同实现后,将其中一种我认为模拟的比较好的方案做个总结。

首先定义一个ClassInfo类:

typedef Resource* (*ResourceConstructorFn)(void);

class ClassInfo
{
public:
    ClassInfo(int type, ResourceConstructorFn creator):m_creator(creator)
    {
        Resource::regist(this);
    }
    
    Resource* create_resource()
    {
        return m_creator ? (*m_creator)() : 0;
    }
    
    ResourceConstructorFn m_creator;
};


Resource类便是我们需要反射创建的类的基类了。定义如下:

class Resource
{
public:
    Resource();
    virtual ~Resource() = 0;
    static Resource* get_resource(string name)
  {

if(m_map_resource.find(name) != m_map_resource.end())
{
  Resource* res = m_map_resource[name]->create_resource();
  return res;
}
else
{
  return NULL;
}

  }
static void regist(ClassInfo* ci)
    {
        if(ci)
        {
            if(m_map_resource.find(ci->m_type) == m_map_resource.end())
            {
                m_map_resource[ci->m_type] = ci;
            }
        }
    }
    protected:
    static std::map<string, ClassInfo*> m_map_resource; //资源类型与其类信息map,用于创建资源子类
};

ClassInfo类的构造函数里会将自身注册到Resource基类当中,然后Resource类的get_resource(string name)函数就可以根据注册的信息创建对应的Resource子类了。因此,我们只需让所有Resource子类都有一个ClassInfo对像就行了。于是添加以下宏来实现:

//用于创建资源,所有继承Resource类的子类,其定义结尾应当加此宏。
#define DECLARE_RESOURCE(class_name) \
private:\
    static ClassInfo ci; \
public:\
    ClassInfo* get_class_info(){return &ci;}\
    static Resource* create_resource(){return new class_name();}

//绑定资源及其类型,用于创建资源,所有继承Resource类的子类,其实现中应当加此宏。    
#define BIND_RESOURCE_TYPE(class_name, name) \
ClassInfo name::ci(name, (ResourceConstructorFn)&class_name::create_resource);

class A:Resouce
{
 DECLARE_RESOURCE(A) 
};
BIND_RESOURCE_TYPE(A, "A")

只要在扩展每个Resource的子类的时候,都加入DECLARE_RESOURCEBIND_RESOURCE_TYPE这两个宏,由于静态变量会在程序执行最开始就初始化,也就是A类的ci成员会在一开始就将create_resource()函数注册到Resource基类的m_map_resource中,

所以,要得到A类的实例,变只需要根据类名调用Resource::get_resource("A")即可。

虽然实现逻辑有点复杂,还需要在定义子类时加入两个宏,但是还是可以模拟一下反射的功能的。

原文地址:https://www.cnblogs.com/yutongqing/p/6472148.html