zoukankan      html  css  js  c++  java
  • 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")即可。

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

  • 相关阅读:
    118. Pascal's Triangle
    697. Degree of an Array
    1013. Partition Array Into Three Parts With Equal Sum
    167. Two Sum II
    ol7 禁用mysql 自启动
    pgsql常用命令
    清空history 命令记录
    pgsql启动报错
    在rhel 7.4中安装glibc-devel-2.17-196.el7.i686包的过程详录
    postgresql-9.2 install
  • 原文地址:https://www.cnblogs.com/yutongqing/p/6472148.html
Copyright © 2011-2022 走看看