天生限制
C++语言本身不支持反射机制,但C++对象总是要序列化的,序列化就是存储到磁盘上,将对象变成一定格式的二进制编码,然后要用的时候再将保存在磁盘上的二进制编码转化成一个内存中的对象,这个过程中总是需要有一个指示来告诉编译器要生成什么样的对象,最简单的方式当然就是类名了,例如:将一个ClassXXX对象存储到磁盘上,再从磁盘读取的时候让编译器根据“ClassXXX”名称来new一个对象。
但是问题出现了,C++语言本身不支持反射,也就是说不能通过如下方式生成一个对象:
ClassXXX object = new “ClassXXX”;
工厂方法
当然,这样的方法不行,那我们只有另辟蹊径。最简单的就是工厂方法了:
ClassXXX* object = FactoryCreate(“ClassXXX”);
至于FactoryCreate的设计就很简单了,if的集合就可以了:
if(name = “ClassXXX”)
return new ClassXXX;
if(name = “ClassYYY”)
return new ClassYYY;
看起来不错,来个类名就可以生成对应的对象,功能上解决了根据类名生成对象的问题。
假如以上所有的代码都有你一个人编写,那当然问题不大,但是假如有一天你的公司扩大了,这部分代码由两个不同的组A和B来维护,啊哈,问题来了,A组每添加或者修改一个类,都要通知B组更新FactoryCreate函数,也就是说A组的任何关于类的修改,都需要B组来修改,但实际上B的修改不产生任何价值,而且不胜其烦,永无止尽!!如果哪天来了一个新员工,由于对这个规定还不清楚,忘记了通知,那就完了:编译通不过!
一个公司内都会产生如此多的问题,更何况微软这样的大公司是面对全球的各种各样的客户,如果微软把这部分做进框架代码中,呵呵,那微软所有的人不用干其他事情了,每天处理来自全球的要求修改FactoryCreate函数的邮件和电话就够他们忙的了:)
回调工厂
既然此路不好走,那么我们再考虑其它方法吧,一个可选的方法是将FactoryCreate做成回调函数,框架提供注册接口RegisterFactoryCreate,框架函数如此实现:
typedef CObject* (*FactoryCreate_PTR)(String name);
RegisterFactoryCreate(FactoryCreate_PTR fc_ptr);
应用代码如此实现:
CObject* MyFactoryCreate(String name);
RegisterFactoryCreate(MyFactoryCreate);
到这里一个框架和应用分离的反射机制基本实现了,你是否长吁一口气,然后准备泡杯咖啡,稍微放松一下呢?确实可以稍微休息一下了,毕竟我们完成了一件非常了不起的事情,让C++实现了反射。
但你只悠闲了一两天,麻烦事就来了。员工张三跑来向你抱怨“老大,李四注册的反射函数把我的覆盖了”!哦,你仔细一看,My god,这个注册函数只能注册一个反射函数,后注册的就把前面的覆盖了!
怎么办?总不可能又要求所有的类的反射函数都在一个工厂里实现吧,那这样就又回到了工厂方法中描述的时代了。
当然,聪明的你估计很快就能想出问题的解决方法,将RegisterFactoryCreate函数稍加修改就能满足要求了,新的实现如下:
RegisterFactoryCreate(FactoryCreate_PTR fc_ptr,String className)
然后要求每个类都单独写自己的FactoryCreate_PTR函数,类似如下方式:
static CObject* ClassXXX::CreateClassXXX (){
return new ClassXXX;
};
static CObject* ClassYYY::CreateClassYYY(){
return new ClassYYY;
};
到此为此终于大功告成,通过我们的智慧实现了C++的反射功能!一股自豪感油然升起:)
最后的杀手锏:宏
当你为自己的聪明才智而骄傲的时候,那边却有几个开发的兄弟在发出抱怨“唉,这么多相似的函数,看着都眼花,每个类都要写,烦死了”。
或者有一天,你要在每个类的CreateClass函数中增加一个其它功能(例如日志),那么开发的兄弟真的是要烦“死了”!!!
其实仔细一看,包括函数申明、函数定义、函数注册,每个类的代码除了类名外其它都是一模一样的,有没有简单的方法呢?
肯定是有的,这个方法就是宏了,按照如下方法定义宏:
#define DECLARE_CLASS_CREATE(class_name) \
static CObject* CreateClass## class_name ();
#define IMPL_CLASS_CREATE(class_name) \
static CObject* CreateClass## class_name (){ \
return new class_name; \
};
#define REG_CLASS_CREATE(class_name) \
RegisterFactoryCreate(class_name::CreateClass## class_name, #class_name);
注:##是连接符,将两个字符串连接起来,#是将class_name作为字符串处理。
大家可以比较一下,用了宏和不用宏是不是代码感觉完全不一样呢?而且那天需要增加一个简单的功能,只需要改宏定义就ok了,不要全文搜索所有相关函数,然后一个一个的重复添加。
到这里才真正是大功告成!!
分享到:
相关推荐
以下是对"C++实现反射demo"的详细解析。 反射的核心概念是能够动态地获取类的信息,包括类名、成员变量、方法等,并能在运行时创建和调用对象。在C++中,这通常通过元编程(Meta-Programming)来实现,元编程是一种...
在C++实现反射时,我们可以创建一个单例类`ReflectionManager`,这个类将存储所有已知类的信息。为了实现这一点,每个类需要声明一些元数据,例如类名、成员函数等。这些元数据可以存储在一个结构体或类中,然后在类...
在编程领域,反射是一种强大的能力,它允许程序在运行时检查自身,并且能够动态地访问、操作类的属性和方法。...对于那些需要在运行时动态操作对象属性和行为的场景,了解如何实现反射机制是非常有价值的。
本文将深入探讨C++实现反射的原理及其应用。 反射的基本思想是让程序能够动态地获取类型信息,并能够在运行时创建和操作对象。在C++中,通常通过元编程(Meta-programming)技术来实现类似的功能。元编程分为编译时...
为了实现反射,必须有一种机制将执行状态转换为数据,这个过程称为具化。具化是实现反射的基础,它使得程序能够动态地操纵类型信息和方法。 由于Java和.NET平台上反射技术的成功应用,反射技术从理论研究走向了实用...
尽管C++标准库未直接支持反射机制,但通过精心设计和利用C++的特有特性,如工厂模式、模板元编程和类型特质等,可以有效地实现反射的功能。这种方式不仅增加了代码的灵活性和可扩展性,还使得C++在动态类型处理和...
以下是一个简单的C++实现反射的示例: ```cpp #include #include // 假设我们有一个基类 class Reflectable { public: virtual ~Reflectable() {} }; // 类型注册 std::map, int> typeRegistry; // 元数据...
c++ 反射实现原理代码;c++ 反射实现原理代码;c++ 反射实现原理代码;c++ 反射实现原理代码;c++ 反射实现原理代码;
由于C++原生并不支持反射,所以开发者通常需要通过一些技巧来模拟实现。这篇代码和文章将探讨如何使用模板(template)和元编程(Metaprogramming)技术在C++中模拟反射机制。 首先,我们来看`vfxReflectBase.cpp`...
在大多数传统C++实现中,由于其静态类型系统,反射并不是一个内置的功能。然而,随着C++标准的发展,尤其是C++20引入了元对象系统(Metaclasses)和类表(Class Tables),反射的概念正在逐步实现。在这个“C++反射...
而"cpp-reflect在C++17中轻松实现反射和序列化"的主题则探讨了在C++17标准下,如何利用预C++20的手段来实现类似的功能,这对于想要提前尝鲜或者在不支持C++20的编译器环境下工作的人来说非常有价值。 反射通常包括...
RTTR提供的强大功能和灵活性使得在C++中实现反射和JSON序列化成为可能,即使C++本身不原生支持这些特性。在rttr-master这个压缩包中,应该包含了RTTR库的源码和文档,你可以进一步研究和学习其内部实现和用法。
通常,C++不直接支持反射,但可以通过元编程和自定义机制来实现类似的功能。工厂模式是一种设计模式,用于创建对象,它将对象的创建过程封装起来,使得创建过程独立于使用对象的代码。这里我们将探讨如何结合C++的...
在本文中,我们将深入探讨如何使用 C++ 实现一个简单的 gRPC 服务端 demo。首先,我们需要了解 gRPC 的核心概念和工作原理。 1. **gRPC 基本概念** - **RPC**:远程过程调用,允许一个程序调用另一个位于不同地址...
通常,C++不直接支持反射,但开发者可以通过一些技巧来模拟实现。在这个场景中,我们讨论的是如何通过单例模式、工厂模式和函数指针来实现一种近似反射的效果。 首先,单例模式(Singleton)是一种设计模式,确保一...
本文将深入探讨C++的反射(reflect)特性,并通过一个简单的示例来展示如何实现类对象的方法调用。 反射的核心在于创建一种映射,将编译时的信息(如类型信息)转换为运行时的数据结构,这样就可以在运行时访问这些...