`
wwq100
  • 浏览: 21279 次
  • 性别: Icon_minigender_1
  • 来自: 北京
最近访客 更多访客>>
社区版块
存档分类
最新评论

C++ 反射实现

 
阅读更多

如果你问一个IT人士“C++如何实现类似Java的反射?”,结果会怎样呢?~@#¥%……&*,估计大部分人都会要稍微思考了一下,或者直接说“C++根本就不支持反射的呀!”。

是的,C++语言本身是不支持反射的,但实际应用中总是会有将对象序列化的需求,总不可能C++不支持,我们就不用C++了,既然发明C++的大师们没有考虑这个,那我们只有自己动手了,说过“自己动手,丰衣足食”!

天生限制

C++语言本身不支持反射机制,但C++对象总是要序列化的,序列化就是存储到磁盘上,将对象变成一定格式的二进制编码,然后要用的时候再将保存在磁盘上的二进制编码转化成一个内存中的对象,这个过程中总是需要有一个指示来告诉编译器要生成什么样的对象,最简单的方式当然就是类名了,例如:将一个ClassXXX对象存储到磁盘上,再从磁盘读取的时候让编译器根据“ClassXXX”名称来new一个对象。

但是问题出现了,C++语言本身不支持反射,也就是说不能通过如下方式生成一个对象:

ClassXXX object = newClassXXX”;

工厂方法

当然,这样的方法不行,那我们只有另辟蹊径。最简单的就是工厂方法了:

ClassXXX* object = FactoryCreate(“ClassXXX”);

至于FactoryCreate的设计就很简单了,if的集合就可以了:

if(name = “ClassXXX”)

return new ClassXXX;

if(name = “ClassYYY”)

return new ClassYYY;

看起来不错,来个类名就可以生成对应的对象,功能上解决了根据类名生成对象的问题。

假如以上所有的代码都有你一个人编写,那当然问题不大,但是假如有一天你的公司扩大了,这部分代码由两个不同的组AB来维护,啊哈,问题来了,A组每添加或者修改一个类,都要通知B组更新FactoryCreate函数,也就是说A组的任何关于类的修改,都需要B组来修改,但实际上B的修改不产生任何价值,而且不胜其烦,永无止尽!!如果哪天来了一个新员工,由于对这个规定还不清楚,忘记了通知,那就完了:编译通不过!

一个公司内都会产生如此多的问题,更何况微软这样的大公司是面对全球的各种各样的客户,如果微软把这部分做进框架代码中,呵呵,那微软所有的人不用干其他事情了,每天处理来自全球的要求修改FactoryCreate函数的邮件和电话就够他们忙的了:)

回调工厂

既然此路不好走,那么我们再考虑其它方法吧,一个可选的方法是将FactoryCreate做成回调函数,框架提供注册接口RegisterFactoryCreate,框架函数如此实现:

typedef CObject**FactoryCreate_PTR(String name);

RegisterFactoryCreate(FactoryCreate_PTR fc_ptr);

应用代码如此实现:

CObject* MyFactoryCreateString name;

RegisterFactoryCreate(MyFactoryCreate);

到这里一个框架和应用分离的反射机制基本实现了,你是否长吁一口气,然后准备泡杯咖啡,稍微放松一下呢?确实可以稍微休息一下了,毕竟我们完成了一件非常了不起的事情,让C++实现了反射。

但你只悠闲了一两天,麻烦事就来了。员工张三跑来向你抱怨“老大,李四注册的反射函数把我的覆盖了”!哦,你仔细一看,My god,这个注册函数只能注册一个反射函数,后注册的就把前面的覆盖了!

怎么办?总不可能又要求所有的类的反射函数都在一个工厂里实现吧,那这样就又回到了工厂方法中描述的时代了。

当然,聪明的你估计很快就能想出问题的解决方法,将RegisterFactoryCreate函数稍加修改就能满足要求了,新的实现如下:

RegisterFactoryCreateFactoryCreate_PTR fc_ptrString className

然后要求每个类都单独写自己的FactoryCreate_PTR函数,类似如下方式:

static CObject* ClassXXX::CreateClassXXX (){

return new ClassXXX;

};

static CObject* ClassYYY::CreateClassYYY(){

return new ClassYYY;

};

到此为此终于大功告成,通过我们的智慧实现了C++的反射功能!一股自豪感油然升起:)

最后的杀手锏:宏

当你为自己的聪明才智而骄傲的时候,那边却有几个开发的兄弟在发出抱怨“唉,这么多相似的函数,看着都眼花,每个类都要写,烦死了”。

或者有一天,你要在每个类的CreateClass函数中增加一个其它功能(例如日志),那么开发的兄弟真的是要烦“死了”!!!

其实仔细一看,包括函数申明、函数定义、函数注册,每个类的代码除了类名外其它都是一模一样的,有没有简单的方法呢?

肯定是有的,这个方法就是宏了,按照如下方法定义宏:

#defineDECLARE_CLASS_CREATE(class_name) /

static CObject* CreateClass## class_name ();

#defineIMPL_CLASS_CREATE(class_name) /

static CObject* CreateClass## class_name (){/

return new class_name;/

};

#defineREG_CLASS_CREATE(class_name) /

RegisterFactoryCreate(class_name::CreateClass## class_name, #class_name);

注:##是连接符,将两个字符串连接起来,#是将class_name作为字符串处理。

大家可以比较一下,用了宏和不用宏是不是代码感觉完全不一样呢?而且那天需要增加一个简单的功能,只需要改宏定义就ok了,不要全文搜索所有相关函数,然后一个一个的重复添加。

到这里才真正是大功告成!!

后记

某天分析SpringIOC时,看到Digester最后利用的实际上是Java的反射机制来根据XML文件定义生成Java对象,突发奇想:如果是C++该怎么办?

于是自己就开始分析起来,分析了一段时间突然想起微软的MFC不正是要支持C++对象序列化的吗?

赶紧打开深入浅出MFC,重新将这部分研究了一下。看到微软的天才们在MFC中用宏来实现RTTIDynamic CreateSeralize功能时,我反过来思考“如果是我,我会如何设计?”、“为什么会这么设计”?然后一一分析这些各种可能的实现方式,一步一步的推导,最后发现竟然自然而然的就推出了MFC的这种实现方式!

当然,MFC的实现代码和我给出的代码不一样(注册方式不一样),但设计思想是一样的,各位看官可以自行稍加分析就明白了。

MFC的详细实现可以参考侯捷的《深入浅出MFC》。


分享到:
评论

相关推荐

    c++ 反射实现原理代码;

    c++ 反射实现原理代码;c++ 反射实现原理代码;c++ 反射实现原理代码;c++ 反射实现原理代码;c++ 反射实现原理代码;

    C++反射机制实现

    在讨论C++反射机制实现的过程中,我们首先需要明确反射机制的概念和分类。反射的定义源自人工智能领域,它主要涉及到两种反射结构:结构反射和计算反射。结构反射侧重于元类与类之间的关系,计算反射则关注于计算...

    C++实现的反射+论文原理讲解

    论文《C++反射机制的一种简单实现》可能详细介绍了这种实现方法,包括如何定义元对象,如何存储和检索类型信息,以及如何利用这些信息进行动态操作。论文可能还讨论了性能影响和设计决策,以及如何在实际项目中有效...

    c++实现反射demo

    然而,目前这一特性尚未被所有编译器广泛支持,所以对于需要在现有环境工作的项目,上述自定义的反射实现仍然有其价值。 总的来说,"C++实现反射demo"展示了如何利用C++的模板和宏技术,模拟出类似于其他语言中的...

    用C++实现反射的例子

    总的来说,C++的反射实现通常需要深入理解模板元编程和宏预处理器的使用。尽管这在某些情况下可能不是最佳实践,但这种技术可以扩展C++的静态类型系统的功能,使代码更加灵活。对于那些需要在运行时动态操作对象属性...

    C++实现反射机制

    本篇将深入探讨如何利用单例模式和工厂模式来构建一个简单的C++反射机制。 首先,我们需要理解单例模式和工厂模式的基本概念。单例模式是一种设计模式,确保一个类只有一个实例,并提供全局访问点。这在创建昂贵的...

    c++反射工厂 (xxxx)

    ### C++反射基础 在没有内置反射的情况下,C++程序员经常使用预处理器宏、模板元编程或动态类型系统(如RTTI,运行时类型信息)来模拟反射。例如,通过定义类的元数据结构,可以存储类名、成员函数指针等信息,然后...

    C++反射机制

    ### C++反射机制详解 #### 引言:C++与反射机制 在现代软件开发领域,反射机制(Reflection)作为一种强大的编程技术,被广泛应用于多种编程语言中,如C#、Java等。它允许程序在运行时检查和修改自身结构与行为,...

    c++反射 类序列化为json

    通常,C++不直接支持反射,但可以通过第三方库来实现,RTTR(Runtime Type Reflection)就是这样一个库,它提供了一种强大的方式来实现C++的反射功能。 RTTR库允许开发者在程序运行时动态地访问和操作类型信息。...

    C++模拟实现反射的代码和代码解析文章

    由于C++原生并不支持反射,所以开发者通常需要通过一些技巧来模拟实现。这篇代码和文章将探讨如何使用模板(template)和元编程(Metaprogramming)技术在C++中模拟反射机制。 首先,我们来看`vfxReflectBase.cpp`...

    C++反射的例子(VC++).rar

    在这个“C++反射的例子(VC++)”压缩包中,我们可以预期找到一个简单的示例,演示如何在Visual C++环境下实现或模拟反射机制。 反射的主要应用包括:动态类型检查、运行时代码生成、自动序列化、插件系统以及更方便...

    通过C++来实现类似JAVA和C#的反射原理例子程序

    下面我们将详细探讨如何通过C++实现类似Java和C#的反射原理。 首先,理解反射的基本概念:反射允许代码在运行时获取类型信息,如类名、方法、属性等,并能动态地调用方法或访问成员变量。在Java和C#中,有内建的`...

    CLI/C++反射机制交互C#、C++

    标题中的“CLI/C++反射机制交互C#、C++”指的是在C#中通过反射机制来调用由C++/CLI编译的DLL中的方法。反射是.NET框架提供的一种强大功能,它允许程序在运行时动态地获取类型和对象的信息,并能创建类型实例、调用...

    C++反射的例子

    这个“C++反射的例子”压缩包文件很可能是包含了一个或多个示例代码,用于演示如何在C++中实现和使用反射。 在C++中,反射并非原生支持的功能,但随着C++20标准的发布,正式引入了对反射的支持。C++20的反射库提供...

    C++反射动态创建所需类的实例

    通常,C++不直接支持反射,但开发者可以通过一些技巧来模拟实现。在这个场景中,我们讨论的是如何通过单例模式、工厂模式和函数指针来实现一种近似反射的效果。 首先,单例模式(Singleton)是一种设计模式,确保一...

    C++反射的例子源代码.rar

    总的来说,C++反射的例子源代码将提供一个实践性的教程,帮助开发者理解如何在C++中实现类似动态语言那样的元编程能力。通过学习和分析这个例子,你可以掌握如何在自己的项目中利用反射来提升代码的灵活性和可扩展性...

Global site tag (gtag.js) - Google Analytics