使用C++模拟实现 C# 中的反射功能
2016-03-24 19:47
465 查看
最近在看设计模式的相关内容, 看到抽象工厂模式这章节的时候, 书上介绍说, 抽象工厂模式在替换具体工厂类型的时候比较方便, 但是在涉及添加一个新的产品类的时候, 需要修改现有的工厂来支持这个新的产品, 违反了开闭原则。 一般可以采用简单工厂并借助反射的功能, 解决这个不足。
C# 中自带反射的功能, 但是我们C++居然没有, 这个一个比较讨厌的地方, 于是, 我们研究了相关内容, 参考了一些文章, 终于弄明白了这里面的基本原理, 主要参考文章: C++反射的实现
下面对实现的原理做一些解释:
我们主要定义了两个类, CObject 作为所有需要使用反射功能的对象的基类, 以及 CClassInfo 记录派生自CObject 对象的类名及其相应的我们自己定义的 构造函数指针(非C++中的构造函数的概念)
我们为每个派生自CObject 的对象, 添加一个 CClassInfo 类型的静态成员,当这个成员发生构造的时候, 会将这个类进行注册, 注册到一个全局的 map 对象中去。
也就是说, 每当产生一个CObject 的派生类的时候, 都会自动的将他们的类名 和 相应类的指针 存储到 map 中去。
当需要由字符串构建一个类对象的时候, 我们只要访问这个map 对象, 获取到相应的类的指针, 调用我们的构造函数, 就可以实现 类对象的构造了。
思路非常清晰, 但是还剩下一个问题。 如何获取一个类的类名, 这就需要借助我们的 预处理宏了
使用这段代码就可以获取变量的名称了, ie, #加变量, 可以获取变量的名字。
我们在参考上面这篇参考文章中代码思想的前提下, 写出了自己的代码,由于使用宏会影响代码的可读性, 我们在一个对象类中将宏展开, 方便阅读。
运行效果图:
代码部分:
base.h
obj.h
main.cpp
C# 中自带反射的功能, 但是我们C++居然没有, 这个一个比较讨厌的地方, 于是, 我们研究了相关内容, 参考了一些文章, 终于弄明白了这里面的基本原理, 主要参考文章: C++反射的实现
下面对实现的原理做一些解释:
我们主要定义了两个类, CObject 作为所有需要使用反射功能的对象的基类, 以及 CClassInfo 记录派生自CObject 对象的类名及其相应的我们自己定义的 构造函数指针(非C++中的构造函数的概念)
我们为每个派生自CObject 的对象, 添加一个 CClassInfo 类型的静态成员,当这个成员发生构造的时候, 会将这个类进行注册, 注册到一个全局的 map 对象中去。
也就是说, 每当产生一个CObject 的派生类的时候, 都会自动的将他们的类名 和 相应类的指针 存储到 map 中去。
当需要由字符串构建一个类对象的时候, 我们只要访问这个map 对象, 获取到相应的类的指针, 调用我们的构造函数, 就可以实现 类对象的构造了。
思路非常清晰, 但是还剩下一个问题。 如何获取一个类的类名, 这就需要借助我们的 预处理宏了
#define GetName(name) #name
使用这段代码就可以获取变量的名称了, ie, #加变量, 可以获取变量的名字。
我们在参考上面这篇参考文章中代码思想的前提下, 写出了自己的代码,由于使用宏会影响代码的可读性, 我们在一个对象类中将宏展开, 方便阅读。
运行效果图:
代码部分:
base.h
#ifndef _BASE_H_ #define _BASE_H_ #include <string> #include <map> #include <iostream> using std::string; using std::map; using std::cout; using std::endl; class CObject; class CClassInfo; // t特定的函数指针 typedef CObject * (*ClassConstructor)(); // 维护类名 和 特定函数指针的基础结构 map<string, CClassInfo *> mymap; // 获取类名 #define GetClassName(name) #name // 注册 类名 和 相应的 createObj 函数指针 void RegisterClass(CClassInfo * c); /************************************************************************/ /* 对象信息类, 记录类名 和 我们专门设置的 createObj 函数指针信息 */ /************************************************************************/ class CClassInfo { public: CClassInfo(string name, ClassConstructor ctor) : name(name), ctor(ctor){ // 构造过程中 实现注册, 将相应信息加入 mymap RegisterClass(this); } CObject * createObj(){ return (ctor == nullptr) ? nullptr : (*ctor)(); } public: string name; ClassConstructor ctor; }; /************************************************************************/ /* 所有接受管理的 使其可以反射的 对象基类 */ /************************************************************************/ class CObject{ public: CObject() = default; virtual ~CObject(){}; static CObject * createObj(string name){ if (mymap.find(name) != mymap.end()){ return mymap[name]->createObj(); } return nullptr; } static void registerClass(CClassInfo * c){ mymap.insert(make_pair(c->name, c)); } }; //************************************ // Method: RegisterClass // FullName: RegisterClass // Access: public // Returns: void // Qualifier: 注册 类名 和 相应的 createObj 函数指针 // Parameter: CClassInfo * c //************************************ void RegisterClass(CClassInfo * c){ CObject::registerClass(c); } // 定义宏 #define DECLARE_CLASS(CLASS_NAME) \ static CClassInfo m_class; \ static CObject * createObj(){ \ return new CLASS_NAME; \ } #define IMPLETE_CLASS(CLASS_NAME) \ CClassInfo CLASS_NAME::m_class(GetClassName(CLASS_NAME), createObj); #endif // _BASE_H_
obj.h
#ifndef _OBJ_H_ #define _OBJ_H_ #include "Base.h" /************************************************************************/ /* 实际对象A 展开宏之后 */ /************************************************************************/ class objA : public CObject{ public: static CClassInfo m_class; static CObject * createObj(){ return new objA; } objA(){ cout << "objA constructor" << endl; } }; CClassInfo objA::m_class(GetClassName(objA), createObj); /************************************************************************/ /* 实际对象B 未展开宏之 */ /************************************************************************/ class objB : public CObject{ public: DECLARE_CLASS(objB); objB(){ cout << "objB constructor" << endl; } }; IMPLETE_CLASS(objB); #endif // _OBJ_H_
main.cpp
#include "Base.h" #include <memory> #include "obj.h" using namespace std; int main(){ CObject * pobjA = CObject::createObj("objA"); CObject * pobjB = CObject::createObj("objB"); system("pause"); return 0; }
相关文章推荐
- C++扬帆远航——19(斐波那契数列第20项)
- C++: 实现双向链表(例题讲解)
- C++扬帆远航——18(项目五2,递归式)
- C语言用递归方法求最优次数“挑选伪金币”的问题。
- C++扬帆远航——17(递归函数求阶乘)
- gcc编译C++程序
- 12个有趣的C语言面试题
- 字符串分割(C++)
- C++扬帆远航——16(猜数字)
- C++反射的实现
- C++开源项目列表
- 洛谷 P1579
- 欢迎使用CSDN-markdown编辑器
- 2016蓝桥杯省赛 C语言A组
- C++扬帆远航——15(项目二,太乐了)
- CSP考试 2015年9月第1题 数列分段 C语言实现
- C++文件操作
- C++动态内存分配
- c++作业2
- C++中cin、cin.get、cin.getline用法辨析