c++ so 反射_C++实现反射机制

C++本身是不支持反射机制的,而在最近项目中很多地方用到了工厂类,这样就增加了代码中分支语句,降低了代码的可读性,于是就模仿C#中的反射机制,用函数指针自己实现了C++的反射。下面是实现时写的demo介绍。

主要特点有以下几点:

用map保存了字符串到动态类生成的函数指针的映射。

使用类名注册,根据不同的类名字符串构造成不同的类对象。

代码实例:Singleton类

头文件

1 #pragma once

2

3 template

4 classSingleton5 {6 public:7 using object_type =T;8 structobject_creator9 {10 object_creator() { Singleton::instance(); }11 };12

13 staticobject_creator creator_object;14 public:15 static object_type*instance()16 {17 staticobject_type _instance;18 return &_instance;19 }20 };21 template typename Singleton::object_creator Singleton::creator_object;

View Code

代码实例:ClassFactory类

头文件

1 #pragma once

2 #include "Singleton.h"

3

4 #include

5

6 classItem;7

8 //定义一个返回值为void* 参数为null的函数指针

9 typedef void* (*ItemObject)();10

11 structItemObjectClass12 {13 explicitItemObjectClass(ItemObject item) : itemObject(item) {}14 ItemObject itemObject;15 };16

17

18 //作为所有类的工厂,如有需要某一类型的类的工厂可以继承此类

19 class ClassFactory : public Singleton

20 {21 public:22 ClassFactory();23 ~ClassFactory();24

25

26 //************************************27 //Method: CreateItem 创建类,28 //FullName: ClassFactory::CreateItem29 //Access: public30 //Returns: void *31 //Qualifier:32 //Parameter: string className33 //************************************

34 void * CreateItem(string className); //返回void *减少了代码的耦合35

36 //

37 //************************************38 //Method: RegisterItem39 //FullName: ClassFactory::RegisterItem40 //Access: public41 //Returns: void42 //Qualifier:43 //Parameter: const string & className 要创建类的类名44 //Parameter: ItemObject item 函数指针,该指针在宏REGISTER_CLASS中被绑定45 //************************************

46 void RegisterItem(const string&className, ItemObject item);47

48 private:49 //缓存类名和生成类实例函数指针的map,ItemObject实际上是一个函数指针

50 mapobjectItems;51 };

View Code

源文件

1 #include "stdafx.h"

2 #include "ClassFactory.h"

3

4

5

6 ClassFactory::ClassFactory()7 {8 }9

10

11 ClassFactory::~ClassFactory()12 {13 for(auto it : objectItems)14 {15 if (it.second !=nullptr)16 {17 deleteit.second;18 it.second =nullptr;19 }20 }21 objectItems.clear();22 }23

24

25 //返回void *减少了代码的耦合

26 void * ClassFactory::CreateItem(stringclassName)27 {28 ItemObject constructor =nullptr;29

30 if (objectItems.find(className) !=objectItems.end())31 constructor = objectItems.find(className)->second->itemObject;32

33 if (constructor ==nullptr)34 returnnullptr;35

36 //调用函数指针指向的函数 调用REGISTER_CLASS中宏的绑定函数,也就是运行new className代码

37 return (*constructor)();38 }39

40 //ItemObject相当于一个回掉函数

41 void ClassFactory::RegisterItem(const string&className, ItemObject item)42 {43 map::iterator it =objectItems.find(className);44 if (it !=objectItems.end())45 objectItems[className]->itemObject =item;46 else

47 objectItems.insert(make_pair(className, newItemObjectClass(item)));48 }

View Code

工厂类实例主要时用来生成每个类的实例,该类的优点是,编写完成后,不需要改动,就可以生成想要的类的实例(减少了增加或者删除类时候要修改相应分支的代码)。

代码实例:REGISTERCLASS类  该类是一个宏定义,是为了实现动态类型的创建

头文件

1 #pragma once

2

3

4 //该宏定义实现了一个动态类的创建,5 //## 合并操作符 将操作两边的字符合并成一个新的标识符,合并后新的标识符不是字符串6 //# 构串操作符 它将实参的字符序列(而不是实参代表的值)转换成字符串常量, 转换后是一个字符串7 //class className##Helper : 如className是FileItem,程序将会生成一个FileItemHelper类。8 //构造函数 : 调用工厂类的注册函数,实现了类名和生成类实例函数的绑定9 //CreatObjFunc函数 : 生成一个类实例 比如className是FileItem,则new FileItem. 返回void *减少了代码的耦合

10

11 #define REGISTERCLASS(className) \

12 classclassName##Helper { \13 public: \14 className##Helper() \15 { \16 ClassFactory::instance()->RegisterItem(#className, className##Helper::CreatObjFunc); \17 } \18 static void*CreatObjFunc() \19 { \20 return newclassName; \21 } \22 }; \23 className##Helper className##helper;24 //定义了一个成员变量,如FileItemHelper类的成员变量 FileItemhelper

View Code

上述类型都是为反射动态创建类型准备的类,相当于是工具类,下面就是需要创建的动态类型的实例类介绍。

代码实例:Object类  是整个动态类型的基类,可有可无,在这里添加是为了方便扩展。

头文件

1 #pragma once

2

3 //所有类的基类

4 classObject5 {6 public:7 Object();8 virtual ~Object();9

10 const string& GetClassName() const { returnclassName; }11

12 protected:13 stringclassName;14 };

View Code

源文件

1 #include "stdafx.h"

2 #include "Object.h"

3

4

5 Object::Object()6 {7 }8

9 Object::~Object()10 {11

12 }

View Code

代码实例:Item类  所有Item的基类

头文件

1 #pragma once

2 #include "Object.h"

3

4 //所有Item的基类

5 class Item : publicObject6 {7 public:8 Item();9 virtual ~Item();10

11 virtual void Print() = 0;12

13 };

View Code

源文件

1 #include "stdafx.h"

2 #include "Item.h"

3

4

5 Item::Item()6 : Object()7 {8 }9

10

11 Item::~Item()12 {13 }

View Code

该类是所有Item类型类的基类,下面将列举FileItem和ConsoleItem作为该类的派生类来具体实现和使用派生类的动态类型生成。

代码实例:FileItem类

头文件

1 #pragma once

2 #include "Item.h"

3

4 class FileItem : publicItem5 {6 public:7 FileItem();8 ~FileItem();9

10 virtual void Print() override;11

12 };

View Code

源文件

1 #include "stdafx.h"

2 #include "FileItem.h"

3

4

5 FileItem::FileItem()6 : Item()7 {8 className = "FileItem";9 }10

11

12 FileItem::~FileItem()13 {14 }15

16 voidFileItem::Print()17 {18 cout << className <

View Code

代码实例:ConsoleItem类

头文件

1 #pragma once

2 #include "Item.h"

3

4 class ConsoleItem : publicItem5 {6 public:7 ConsoleItem();8 ~ConsoleItem();9

10 virtual void Print() override;11

12 };

View Code

源文件

1 #include "stdafx.h"

2 #include "ConsoleItem.h"

3

4

5 ConsoleItem::ConsoleItem()6 : Item()7 {8 className = "ConsoleItem";9 }10

11

12 ConsoleItem::~ConsoleItem()13 {14 }15

16 voidConsoleItem::Print()17 {18 cout << className <

View Code

到此为止,使用单例,工厂和函数指针来完成的反射机制已完成,现在就是怎么来使用该反射机制。那么在main函数中将会给出使用实例:

main函数

1 //main.cpp: 定义控制台应用程序的入口点。2 //3

4 #include "stdafx.h"

5

6 #include "ClassFactory.h"

7 #include "FileItem.h"

8 #include "ConsoleItem.h"

9 #include "REGISTERCLASS.h"

10

11 //类型注册,必须注册才能使用,不注册降不会动态生成需要的类的实例

12 REGISTERCLASS(FileItem)13 REGISTERCLASS(ConsoleItem)14

15

16 intmain()17 {18 FileItem* fileItem = static_cast(ClassFactory::instance()->CreateItem("FileItem"));19 fileItem->Print();20 deletefileItem;21

22 ConsoleItem* consoleItem = static_cast(ClassFactory::instance()->CreateItem("ConsoleItem"));23 consoleItem->Print();24 deleteconsoleItem;25

26 return 0;27 }

View Code

该反射机制是每一次CreateItem就会创建一个新的类实例,所有使用完成后,需要我们手动调用delete来释放掉该类的实例。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值