C++反射机制的实现

导读(反射简介)

Reflection 是 Java 程序开发语言的特征之一,它允许运行中的 Java 程序对自身进行检查,或者说"自审",并能直接操作程序的内部属性。即可以在运行时加载、探知、使用编译期间完全未知的classes。换句话说,Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括methods定义),并生成其对象实体、或对其fields设值、或唤起其methods 即有类似如下语句

ClassA objA = ReflexCreat("ClassA")

这也是程序序列化的关键,可以吧相关的类对象以字符串的形式存贮到磁盘,然后利用反射机制读取序列化文件还原系统状态

然而遗憾的是 C++ 并不支持这一机制,但是在实际使用中这是一个很nice的功能,对与 C++ 的fans来说这个可是一个不怎么好的消息

但是考虑到MFC中的 序列化 功能,C++ 肯定也是有办法实现反射的功能的,下面就一起来探讨下C++ 反射机制的实现

一、实现(简单工厂)

学过设计模式的人对于 简单工程模式 肯定不会陌生,我们可以通过建立一个简单工厂模式,利用工厂通过类型名称帮助我们得到类的实体对象

代码形式如下

客户端Client直接如下使用就好了

这样好像我们实现了反射这一简单功能,但是仔细想想这么做仿佛有所不妥,每添加一个新的类,我们就需要在工厂方法中添加分支语句,这样做不但使得代码复杂化,同时也违背了设计模式的开闭原则,所以我们需要换一种方法来解决这个问题

二、实现&进阶(自动注册hash表,回调函数)

需要解决的几个要点
  • 定义回调函数指针,指向创建类实例的回调函数
  • 一个带有hash表的工厂类,用 '类的名称' 和 '指向创建类实例的回调函数的函数指针' 作为键值对
  • 实现hash表的自动注册

如果实现了以上几点,基本上 C++下简单的反射功能就完成了

现在我们来一步一步解决以上问题(将整个反射的实现封装到Reflex.h和Reflex.cpp中)

  • 带有hash表的Reflex类的实现(也是需要反射支持的类的基类)

  • 定义回调函数函数指针,完成hash表自主注册的ClassInfo类

好了,到目前位置我们的 局 已经铺的差不多了,现在就是具体怎么用上我们的 反射模块

方法如下
  • 新定义的类若需要 反射支持 需要继承 基类 Reflex
  • 在新类中定义并实现 返回自身对象指针的函数,用来作为回调函数指针指向的函数
  • 持有一个静态ClassInfo对象,并使用类名和函数指针初始化,完成hash表的注册

需要反射支持的CTest类的申明如下

  • 客户端Client调用情况如下

三、代码简化&宏(降低使用成本)

通过之前的代码我们已经在C++中实现了反射,但是可能大家发现了,每一个需要反射支持的类,我们都需要额外的添加一些代码,来保证反射模块的正常运作,而且这一部分除了类的名称之外就没有了什么不同。

聪明的你可能已经想到了,没错就是C+ +的宏,虽然C++的作者极力反对宏的使用,但是那啥你懂的(懒人就是理由多~),当然之前学习Windwos程序设计的时候,在MFC中微软的小哥哥们那才叫把宏玩的了个溜

  • 言归正传,在基类Reflex.h中加入这一大段宏

  • 于是乎,新申请的类就可以简化成酱紫

四、结语

在这儿说一下宏里面的东西吧

  • 最简单的 \就是当前宏的定义除了本行下面还有,告诉编译器后面的一起处理

#define OUT(name) printf(#name);

  • 以这个为例其中的 #name之前的 #就表示把name格式化为字符串

#define T(name) Class## name

  • 这里的 ## name 中的 ##就是连接符的意思,Class和可变字符name连接成一个字符串

到此C++中简单反射的实现就告一段落,若有错误,欢迎指正

繁夜

发表评论


:[微笑]::[撇嘴]::[色]::[发呆]::[得意]::[流泪]::[害羞]::[闭嘴]::[睡]::[大哭]::[尴尬]::[发怒]::[调皮]::[呲牙]::[惊讶]::[难过]::[酷]::[冷汗]::[抓狂]::[吐]::[偷笑]::[可爱]::[白眼]::[傲慢]::[饥饿]::[困]::[惊恐]::[流汗]::[憨笑]::[大兵]::[奋斗]::[咒骂]::[疑问]::[嘘...]::[晕]::[折磨]::[衰]::[骷髅]::[敲打]::[再见]::[擦汗]::[抠鼻]::[鼓掌]::[糗大了]::[坏笑]::[左哼哼]::[右哼哼]::[哈欠]::[鄙视]::[委屈]::[快哭了]::[阴险]::[亲亲]::[吓]::[可怜]::[笑哭]::[doge]::[泪奔]::[无奈]::[托腮]::[斜眼笑]::[喷血]::[惊喜]::[骚扰]::[小纠结]::[我最美]::[羊驼]::[幽灵]::[吃]::[OK]::[爱你]::[抱拳]::[勾引]::[强]::[弱]::[拳头]::[爱心]::[喝彩]::[西瓜]::[啤酒]::[玫瑰]::[凋谢]::[礼物]::[拥抱]::[月亮]::[菊花]::[棒棒糖]::[蛋]::[刀]::[菜刀]::[炸弹]::[手枪]:

刷新评论

目前评论:2   其中:访客  1   博主  1

    • 堆爱博客 堆爱博客 3    来自「贵州省贵阳市 电信」的朋友 Google Chrome  EVA-TL00 Build/HUAWEIEVA-TL00) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.132 Mobile Safari/537.36

      你的评论输入留言用户信息这为什么和我不一样呢?是你自己改的吧!

        • 繁夜 繁夜 博主 来自「四川省绵阳市 联通」的朋友 UC浏览器 Windows 10

          @堆爱博客 是的基本都是自己改的