美文网首页
C++: 反射的简单实现

C++: 反射的简单实现

作者: 赵伯舟 | 来源:发表于2018-10-02 22:57 被阅读22次

    可先参考:链接

    问题引入

    如何根据一个字符串(类的名称),创建出一个对象

    当我们获得了一个string str = "class_name",那么如何根据这个str来创建一个对象?这时候就需要用到反射。个人对反射的简单理解就是一个字面量来动态创建出一个对象,并可获取对象的成员信息。Java和C#都有完整的反射机制,而C++至今还没有,只能自己动手实现

    实现思路

    1. 可以用一个map来存储类名-构造函数这样的键值对,每新增一个类,就在这个map“注册”一个键值对
    2. 因为这个map是一个全局都会用到的,所以可以使用单例模式
    3. 在进入main函数之前,这个map就应该生成好,即每一个类在实例化之前就执行了“注册”的代码,那怎么在main函数之前就执行“注册”代码?答案可参见下面的代码实现

    代码实现

    #include <iostream>
    #include <map>
    #include <memory>
    
    #define FUNC function<void*(void)>
    
    using namespace std;
    
    class Reflector
    {
    private:
        map<std::string, FUNC>objectMap;
        static shared_ptr<Reflector> ptr;
    
    public:
        void* CreateObject(const string &str)
        {
            for (auto & x : objectMap)
            {
                if(x.first == str)
                    return x.second();
            }
            return nullptr;
        }
    
        void Register(const string &class_name, FUNC && generator)
        {
            objectMap[class_name] = generator;
        }
    
        static shared_ptr<Reflector> Instance()
        {
            if(ptr == nullptr)
            {
                ptr.reset(new Reflector());
            }
    
            return ptr;
        }
    
    };
    
    shared_ptr<Reflector> Reflector::ptr = nullptr;
    
    class RegisterAction
    {
    public:
        RegisterAction(const string &class_name, FUNC && generator)
        {
            Reflector::Instance()->Register(class_name, forward<FUNC>(generator));
        }
    };
    
    #define REGISTER(CLASS_NAME) \
    RegisterAction g_register_action_##CLASS_NAME(#CLASS_NAME, []()\
    {\
        return new CLASS_NAME(); \
    });
    
    
    class Base
    {
    public:
        explicit Base() = default;
        virtual void Print()
        {
            cout << "Base" << endl;
        }
    };
    REGISTER(Base);
    
    class DeriveA : public Base
    {
    public:
        void Print() override
        {
            cout << "DeriveA" << endl;
        }
    };
    REGISTER(DeriveA);
    
    class DeriveB : public Base
    {
    public:
        void Print() override
        {
            cout << "DeriveB" << endl;
        }
    };
    REGISTER(DeriveB);
    
    int main()
    {
        shared_ptr<Base> p1((Base*)Reflector::Instance()->CreateObject("Base"));
        p1->Print();
    
        shared_ptr<Base> p2((Base*)Reflector::Instance()->CreateObject("DeriveA"));
        p2->Print();
    
        shared_ptr<Base> p3((Base*)Reflector::Instance()->CreateObject("DeriveB"));
        p3->Print();
    }
    

    上述代码中的Reflector使用了单例模式,维护一个存储[类名: 构造器]map,每新增一个类,就会通过宏REGISTER来为这个新增一个构造器(其实就是一个lambda表达式,使用new返回一个指针),并用这个构造器和类名生成一个RegisterAction实例,而在RegisterAction的构造函数中进行了“注册”,即通过实例化一个RegisterActionmain函数之前完成了注册

    相关文章

      网友评论

          本文标题:C++: 反射的简单实现

          本文链接:https://www.haomeiwen.com/subject/bioaoftx.html