通过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
2.2对象映射基本类(也可以使用基类)

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

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

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

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

用于注册的函数

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

通过类名获取对象

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)

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

定义用于注册的宏(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

class.h的全部代码

#ifndef CLASS_H
#define CLASS_H
#include<iostream>
#include<functional>
#include <memory>
#include <map>
#include <stdarg.h>
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: "<<m.first<<std::endl;
    }
    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
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)
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);
2.5 Student类
#include"class.h"
#include<vector>
#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);

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;
}

参考
参考
参考

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值