• 通过C++反射实现通过配置类名动态选择执行对象


    1、实现的效果

    项目中有A、B、C三个不同的类。通过配置文件进行选择要执行的类。如配置文件中配置CLASSNAME=A.当我们获取配置中的CLASSNAME时可以进行A类中的方法。

    2、实现

    2.1基类(通过多态进行操作的基类)
    //F.h文件内容
    #ifndef F_H
    #define F_H
    class F
    {
        public:
        virtual void fun()=0;
    };
    #endif
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    2.2对象映射基本类(也可以使用基类)

    以下内容可以保存在一个头文件中 class.h

    //基础类,可以使用基本类F代替
    class ClassMappingObject
    {
        public:
        virtual ~ClassMappingObject()=default;
        virtual void classinit()=0;  //为第二种宏定义提供初始化函数,可以没有
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    使用仿函数进行类型的定义

    using RegisterFunc = std::function<std::unique_ptr<ClassMappingObject>()>;
    inline std::map<std::string ,RegisterFunc> objectMap; //此为全局类的映射表;结构为{类名:类对象}
    //在多个项目中可能会出现重复定义等错误,使用inline进行避免
    
    • 1
    • 2
    • 3

    用于注册的函数

    static void registerObject(const std::string& name,RegisterFunc func) { //传入的进行类名和对象
        objectMap[name] = func;
    }
    
    • 1
    • 2
    • 3

    通过类名获取对象

    template <typename T>
    T* createObject(const std::string& name) {
        if (objectMap.find(name) == objectMap.end()) {
            return nullptr;
        }
        auto ptr = objectMap[name]();
        // 从基类动态转换为外部需要的类型
        return dynamic_cast<T*>(ptr.release());
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    定义用于注册的宏(1)

    template <typename T1>
    std::unique_ptr<ClassMappingObject> class_make_unique() {
        auto* ptr = new T1;
        return std::unique_ptr<ClassMappingObject>(dynamic_cast<ClassMappingObject*>(ptr));
    }
    #ifndef REGISTER_CLASS
    #define REGISTER_CLASS(Type)\
    static struct _ObjectRegisterTask##Type { \
        _ObjectRegisterTask##Type() { \
            registerObject(#Type,class_make_unique<Type>); \
        }; \
    } _task##Type; // NOLINT
    #endif
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    定义用于注册的宏(2)

    //第二种宏定义
    struct RegisterTask {
        RegisterTask( string a) {
            std::cout<<a<<std::endl;
        }
        static string registerfun(const std::string& name,
            std::function<std::unique_ptr<ClassMappingObject>()> func) {
            registerObject(name,func);
            return name;
        }
    };
    
    #ifndef RegisterTask
    #define RegisterTask(Type)\
    static RegisterTask  task##Type(RegisterTask::registerfun(#Type,class_make_unique<Type>));
    #endif
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    class.h的全部代码

    #ifndef CLASS_H
    #define CLASS_H
    #include
    #include
    #include 
    #include 
    #include 
    using namespace std;
    class ClassMappingObject
    {
        public:
        virtual void classinit()=0;
        virtual ~ClassMappingObject()=default;
    };
    
    using RegisterFunc = std::function<std::unique_ptr<ClassMappingObject>()>;
    inline std::map<std::string ,RegisterFunc> objectMap;
    static void registerObject(const std::string& name,RegisterFunc func) {
        objectMap[name] = func;
    }
    
    template <typename T>
    T* createObject(const std::string& name) {
        for(auto m: objectMap)
        {
            // std::cout<<"keys: "<
        }
        if (objectMap.find(name) == objectMap.end()) {
            return nullptr;
        }
        auto ptr = objectMap[name]();
        // 从基类动态转换为外部需要的类型
        return dynamic_cast<T*>(ptr.release());
    }
    
    //第一种宏定义
    template <typename T1>
    std::unique_ptr<ClassMappingObject> class_make_unique() {
        auto* ptr = new T1;
        return std::unique_ptr<ClassMappingObject>(dynamic_cast<ClassMappingObject*>(ptr));
    }
    #ifndef REGISTER_CLASS
    #define REGISTER_CLASS(Type)\
    static struct _ObjectRegisterTask##Type { \
        _ObjectRegisterTask##Type() { \
            registerObject(#Type,class_make_unique<Type>); \
        }; \
    } _task##Type; // NOLINT
    #endif
    
    //第二种宏定义
    struct RegisterTask {
        RegisterTask( string a) {
            std::cout<<a<<std::endl;
        }
        static string registerfun(const std::string& name,
            std::function<std::unique_ptr<ClassMappingObject>()> func) {
            registerObject(name,func);
            return name;
        }
    };
    
    #ifndef REGISTER_CLASS_2
    #define REGISTER_CLASS_2(Type)\
    static RegisterTask  task##Type(RegisterTask::registerfun(#Type,class_make_unique<Type>));
    #endif
    #endif
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    2.3 Per类
    #include"class.h"
    #include"F.h"
    
    class Per:public F,public ClassMappingObject
    {
        public:
        void classinit() //实现ClassMappingObject中函数进行初始化
        {
            tem=10;
            std::cout<<"Per classinit"<<std::endl;
        }
        virtual void fun() //实现F中虚函数进行执行业务
        {
            std::cout<<"Per fun:"<<tem<<std::endl;
        }
        private:
            int tem=0;
    };
    
    //进行注册
    // REGISTER_CLASS(Per);
     REGISTER_CLASS_2(Per)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    2.4 Per1类
    #include"class.h"
    #include"F.h"
    class Per1:public F,public ClassMappingObject
    {
        public:
        void classinit() //实现ClassMappingObject中函数进行初始化
        {
            tem=10;
            std::cout<<"Per1 classinit"<<std::endl;
        }
        virtual void fun() //实现F中虚函数进行执行业务
        {
            std::cout<<"Per1 fun:"<<tem<<std::endl;
        }
        private:
            int tem=0;
    };
    //进行注册
    // REGISTER_CLASS(Per1);
    REGISTER_CLASS_2(Per1);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    2.5 Student类
    #include"class.h"
    #include
    #include"F.h"
    class Student :public F, public ClassMappingObject
    {
        public:
            Student(int a=10){tem = a;}
            virtual void fun()
            {
                std::cout<<"Student fun"<<tem<<std::endl;
            }
            
        public:
            void classinit()
            {
                tem=80;
                std::cout<<"Student classinit"<<std::endl;
            }
        private:
            float tem;
    
    };
    // REGISTER_CLASS(Student);
    REGISTER_CLASS_2(Student);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    3、使用

    #include"classtet1.cpp"
    #include"classtet2.cpp"
    #include"classtet3.cpp"
    #include"F.h"
    int main(int argc, char const *argv[])
    {
        /* code */
        F* ptr = createObject<F>("Per");  //获取基类类型,实现多态
        ptr->fun();
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    参考
    参考
    参考

  • 相关阅读:
    如何在 SAP ABAP ALV 报表里以交通灯的方式显示某一列的值
    外卖小程序:技术实现与关键代码
    spirngcloud的基本介绍与服务注册
    redis集群的搭建
    前端面试题之【Vue】
    centOS安装MySQL详解
    Windows C++程序运行过程中生成dump文件
    Android studio添加aidl文件时,添加按钮为黑色不可点击添加解决办法
    58%数据泄漏由内部引起,防泄密系统助力企业数据安全管理防泄露
    初中级前端程序员面试中小型公司会问哪些问题
  • 原文地址:https://blog.csdn.net/u011573853/article/details/127830309