C++实现反射机制
来源:互联网 发布:成都软件开发工资 编辑:程序博客网 时间:2024/06/04 18:34
话不多说,先上段代码的运行结果:
class TestA:public Object{DECLARE_CLASS()public:TestA() {std::cout << "TestA constructor" << std::endl;}~TestA(){std::cout << "TestA destructor" << std::endl;}};IMPLEMENT_CLASS("testA_interface", TestA)int main() { Object* obj = Object::CreateObject("testA_interface"); delete obj;return 0; }
关键就一个功能——根据字符串创建了类对象
开发中经常会遇到根据不同借口创建不同类实例的情况,一般的做法就是if......else if...else if这样一直判断。比如说接口名是testA_interface,就创建一个TestA对象。如果接口不多还好办,如果接口有成千上万呢?维护起来都难办。那么有没有一种简单的方法?下面慢慢探究。
先说一下一般的思路:
常规的思路就是说建立一个map表,以接口名未key,构造函数为value。但有个问题——我们没办法定义一个构造函数的函数指针!
虽然用map的方法不可行,但这确是一个稚形,以这个为基础,一步一步解决问题(如果是C语言,这里没法用map,其实顶一个结构体就可以了)。
问题一:没法定义构造函数的函数指针
直接从构造函数指针不行,那就加一个中间层,没有什么是不能通过加一层来解决的,如果有,那就加两层。具体的做法就是map中不存构造函数了,而是存另一个类的对象,类的定义如下:
class ClassInfo{public: ClassInfo(){} ClassInfo(const std::string &interface_name, ObjectConstructorFn ctor) { m_interface_name = interface_name; m_object_constructor = ctor; Object::Register(this); } Object *CreateObject()const { return m_object_constructor ? (*m_object_constructor)() : 0; }public:std::string m_interface_name;ObjectConstructorFn m_object_constructor;};
很明显,我们把接口名跟构造函数聚合到了一个结构里面,ObjectConstructorFn是定义的一个函数指针,指向了每个类的构造函数。其实这个地方我们把原来map中的key和value一起当做value了。由此我们可以定义一个map
std::map<std::string, ClassInfo *> *class_info_map = new std::map<std::string, ClassInfo*>();在调用的时候只需要find()->CreateObject()就可以了。
问题二:接口类的管理
就算这个问题不放这里我们也知道,各个接口对应的类它们肯定有一个公有的基类,其次这个地方恩把所有类继承一公有基类也方便我们管理。所有最简基类的定义如下:
class Object{public: Object(){} virtual ~Object(){} static void Register(ClassInfo* ci); static Object* CreateObject(const std::string &interface_name);};关键成员函数有两个,register和createobject,本来是想把这个类设置成单例的,也就是说构造函数应该设为private,但是由于这个类是基类,在创建子类对象的时候会调用基类的构造函数,所以这儿就设成了public,如果createobject来创建对象。而对于register成员函数,它就是根据接口把ClassInfo插入到class_info_map,最简单粗暴的方法就是class_info_map[ci->interface_name] = ci。由前面ClassInfo定义可知,ci已经保存了接口名返回实例的函数。
问题三:子类的实现
目前为止其他都可以了,就差子类的实现了,前面说了,ClassInfo标示了一个接口名和接口的对应关系。所以子类需要包含一个ClassInfo的成员变量。定义两个宏:
#define DECLARE_CLASS() \ protected: \ static ClassInfo ms_classinfo; \ public: \ static Object* CreateObject(); #define IMPLEMENT_CLASS(interface_name, class_name) \ClassInfo class_name::ms_classinfo(interface_name,(ObjectConstructorFn)class_name::CreateObject);\ Object* class_name::CreateObject() \ { return new class_name;}这两个宏定义了所有子类需要实现的部分,所以只要直接引入这两个宏就可以了,在宏中定义了唯一标示接口名与类对应关系的ms_classinfo变量,此外有实现了返回每一个类型对象的CreateObject函数。
下面贴一下完整的代码
#include <iostream>#include <string>#include <map>using namespace std;#define DECLARE_CLASS() \ protected: \ static ClassInfo ms_classinfo; \ public: \ static Object* CreateObject(); #define IMPLEMENT_CLASS(interface_name, class_name) \ClassInfo class_name::ms_classinfo(interface_name,(ObjectConstructorFn)class_name::CreateObject);\ Object* class_name::CreateObject() \ { return new class_name;} class ClassInfo;class Object;typedef Object* (*ObjectConstructorFn)();class Object { protected: Object(){}public: virtual ~Object(){} static void Register(ClassInfo* ci); static Object* CreateObject(std::string name); static std::map<std::string, ClassInfo *> *classInfoMap;}; class ClassInfo { public: ClassInfo(const std::string className, ObjectConstructorFn ctor);ClassInfo();Object *CreateObject()const;public: std::string m_className;ObjectConstructorFn m_objectConstructor;}; std::map<std::string, ClassInfo *> *Object::classInfoMap = new std::map<std::string, ClassInfo*>();void Object::Register(ClassInfo* ci) { if (NULL != ci && classInfoMap->find(ci->m_className) == classInfoMap->end()){ classInfoMap->insert(std::map<std::string, ClassInfo*>::value_type(ci->m_className, ci)); } }Object* Object::CreateObject(std::string name) {std::map<std::string, ClassInfo*>::const_iterator iter = classInfoMap->find(name); if (iter != classInfoMap->end()){return iter->second->CreateObject();}return NULL; } ClassInfo::ClassInfo(const std::string className, ObjectConstructorFn ctor):m_className(className), m_objectConstructor(ctor) { Object::Register(this);}ClassInfo::ClassInfo(){}Object *ClassInfo::CreateObject()const { return m_objectConstructor ? (*m_objectConstructor)() : 0; }class Test:public Object{ DECLARE_CLASS()public: Test(){cout << "Test constructor" << endl;} ~Test(){cout << "Test destructor" << endl;}};IMPLEMENT_CLASS("xxxx", Test)int main() { Object* obj = Object::CreateObject("xxxx"); delete obj; return 0; }熟悉MFC的同学应该知道,MFC中有一个BEGIN_MESSAGE_MAP,它也是实现了不同消息ID与不同处理函数的映射,实现原理和这个类似。
- c 结构体反射机制实现
- 【Object C】 反射机制
- Objective-C反射机制
- 【C#】:浅谈反射机制
- Object-c反射机制
- 【C#】反射机制
- java利用反射实现Object-c中的KVC机制
- 反射机制的实现
- JavaScript 实现反射机制
- iOS实现反射机制
- iOS实现反射机制
- C++实现反射机制
- C++实现反射机制
- C++实现反射机制
- c++实现反射机制
- C++ 实现反射机制
- C++实现反射机制
- C++ 实现反射机制
- Weblogic性能调优基本方案
- centos不联网情况下,使用系统镜像作为本地源yum安装软件
- Android VR 简单开发
- 外观模式
- 如何写出漂亮的有可读性的微信文案?
- C++实现反射机制
- 怎样在asp中产生10个0-99的随机数
- log4j2 入门学习与总结
- Rxjava自定义图片缓存缓存框架(一)
- 队列的实现(数组方式)
- 【Dongle】【Windows】cmd命令提示符(二)
- 网上粘贴一段代码后程序出现错误:error C3872: "0xa0": 此字符不允许在标识符中使用
- Gradle学习笔记(一)环境搭建
- 快速排序代码实现