A design & implementation of reflection in C++

Reflection in C++

前几天看一个java演示的设计模式讲解视频,里面提到了java中的反射机制,感觉反射这个东西很有意思,于是心血来潮想写一个C++中的反射。

反射机制可以简单地理解为:当需要一个类型的实例时,根据类型的名称就能得到一个实例。如下面的函数,

void* CreateClassInstance(const char *name);

这个函数可以根据传入的类型名称创建一个实例。

设计这样一个系统,我们需要对类型的名称和创建实例的方法(如构造函数)进行存储。当然,函数的返回值最好有实际意义,而不是一个无意义的void*。我们给可以被反射的类型取名叫ReflectableClassReflectableClass作为可被反射类型的基类。在这个class中需要对类型的名称和创建实例的方法进行存储,以便需要创建实例时可以进行查找。这里我们用map存储一个“键/值”对,“键”为类型的名称,“值”为创建实例的方法。

static std::map<std::string, FUNC_CREATE_INSTANCE> s_reflectors;

FUNC_CREATE_INSTANCE的定义如下,它是一个函数指针,所指向的函数不带参数。

typedef ReflectableClass* (*FUNC_CREATE_INSTANCE)();

这样便有了如下的类型声明:

class ReflectableClass

{

public:

    ReflectableClass() {}

    virtual ~ReflectableClass() {}

 

    virtual const char* GetClassName() = 0;

 

    static ReflectableClass* CreateClassInstance(const char* name);

    static bool AddInstanceCreator(const char*, FUNC_CREATE_INSTANCE);

 

private:

    static std::map<std::string, FUNC_CREATE_INSTANCE> s_reflectors;

};

GetClassName用来返回每种可被反射的类型的名称,将其声明为纯虚函数,因为ReflectableClass被设计为一个抽象的类型。

CreateClassInstance用来根据传入的类型名称创建并返回一个实例。

AddInstanceCreator用来注册一个新类型。

当我们定义一个新的类型时,如定义一个Human类型,需要有种方式将类型的相关信息自动注册到ReflectableClass中。我们可以为新类型定义一个static的成员,在这个成员被初始化时将类型的信息注册制ReflectableClass中。定义一个新的类ClassInfo来完成这个工作。

class ClassInfo

{

public:

    ClassInfo(const char* name, FUNC_CREATE_INSTANCE creator);

    ~ClassInfo();

};

 

ClassInfo::ClassInfo(const char* name, FUNC_CREATE_INSTANCE creator)

{

    ReflectableClass::AddInstanceCreator(name, creator);

}

 

ClassInfo::~ClassInfo()

{}

 

Human的定义如下:

class Human: public ReflectableClass

{

public:

    Human();

    virtual ~Human();

 

    virtual const char* GetClassName();

    static ReflectableClass* CreateInstance();

 

private:

    static ClassInfo s_classInfoHuman;

 

};

GetClassName是从ReflectableClass中继承并override的虚函数。CreateInstance用来创建Human的实例,即一个FUNC_CREATE_INSTANCE指向的函数。s_classInfoHuman用来注册Human的信息至ReflectableClass中。实现部分的代码如下:

ClassInfo Human::s_classInfoHuman(“Human”, Human::CreateInstance);

 

const char* Human::GetClassName()

{

    return “Human”;

}

 

ReflectableClass* Human::CreateInstance()

{

    return new(std::nothrow) Human;

}

这样我们就完成了一个Human的定义和注册。当需要对Human进行反射时,只需调用“ReflectableClass::CreateClassInstance(“Human”)”即可。这里需要注意一个问题,需确保“ReflectableClass:: s_reflectors”的初始化工作在“Human::s_classInfoHuman”初始化前完成,否则会产生问题。我们可以将ReflectableClassClassInfo的定义和实现放在一个动态连接库中,当定义新类型时加载该库文件。

为方便在新类型中声明和实现static ClassInfo的对象及GetClassNameCreateInstance两个函数,可以定义一些自动化的宏。

完整的代码如下:

ReflectableClass.h

ReflectableClass.cpp

Human.h

Human.cpp

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值