亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C++ > 正文

C++ 實現反射機制

2019-11-08 01:54:29
字體:
來源:轉載
供稿:網友

1. 什么是反射

學過 java 或 C# 的同學應該都知道“反射”機制,很多有名的框架都用到了反射這種特性。這是一種很牛逼的特性,簡單的理解就是只根據類的名字就可以獲取到該類的實例。有人會說,這不是多此一舉嗎?直接 new 一個出來不就行了嗎?像下面這樣:

class Person {public: virtual void show() = 0;}class Allen : public Person { virtual void show() { std::cout << "Hello, I'm Allen!" << std::endl; }}Person *p = new Allen();p->show();

可是有時候,你定義好接口 Person 后,你并不知道誰將會實現該接口,甚至不知道什么時候會實現它。所以此時你無法通過 new 操作符來實例化對象。比如未來的某個時候有人編寫了一個類叫 Luffy,但是此時你不可能實例化 Luffy 這個類,所以你只能編寫下面這種代碼:

std::string className = /*從配置文件中讀取*/Person *p = getNewInstance<Person>(className);

你的程序可以從配置文件中讀取到 "Luffy" 這個字符串保存到變量 className 中。接下來使用函數 getNewInstance 就可以獲取到 Luffy 實例化的對象。

2. C++ 實現反射

很遺憾的是 C++ 并沒有直接從語言上提供這種特性給我們用,不過無所不能的 C++ 可以通過一些 trick 來實現反射這種機制。

2.1 引例

直觀上,我們可以把 getNewInstance 的實現交給未來要使用我們的框架的人:

template<typename T>T* getNewInstance(const std::string& className) { if (className == "Allen") { return new Allen(); } else if (className == "Luffy") { return new Luffy(); }}

如此一來,一旦有新的類實現,我們就必須得修改這個函數,這很容易出錯,維護性很差。

2.2 對象工廠

對象工廠是一種可以間接實例化對象的類。比如:

class ObjectFactory{ virtual ReflectObject* newInstance() = 0;}class ObjectFactory_Allen : public ObjectFactory{ ReflectObject* newInstance(){ // 這里注意一點就是,所有能夠被反射的類都繼承自 ReflectObject 這個類。 return new Allen(); };}

所以,如果有了對象工廠的實例,我們就可以不斷的產生對象了。如下:

ObjectFactory *of = new ObjectFactory_Allen();// 有了對象工廠的實例后,就可以產生 Allen 對象的實例了ReflectObject *allen= of->newInstance();// 接下來可以使用類型轉換,把 allen 對象轉換成 PersonPerson *p = dynamic_cast<Person*>(allen);

2.3 反射器

反射器實際上也是一個類,它管理了類名到對象工廠實例之間的映射關系。反射器對象在程序中是一個全局唯一的對象。這種映射關系看起來就像一張表:

("Allen", Allen 的對象工廠的實例對象);("Luffy", Luffy 的對象工廠的實例對象);("Zoro", Zoro 的對象工廠的實例對象);……

只要未來你想要編寫一個新的類,比如 Allen 類,那么你就必須要同時編寫 Allen 的工廠類 ObjectFactory_Allen,同時,你還得實例化一個這個工廠類的對象 objectFactory_Allen = new ObjectFactory_Allen(),并將 ("Allen", objectFactory_Allen) 這種映射關系保存到反射器中。

反射器的定義如下:

class Reflector{public: Reflector(); ~Reflector(); // 如果你要反射你的類,就必須將你的類名,以及工廠實例對象注冊到反射器中。 void registerFactory(const std::string& className, ObjectFactory *of); // 反射器可以根據對象工廠實例來生產實例對象。請參考 2.2 節 ReflectObject* getNewInstance(const std::string& className);PRivate: std::map<std::string, ObjectFactory*> objectFactories;};

2.4 編寫要被反射類的大致思路

有了上面的基礎好,要想讓你的類被反射,大致有以下幾個步驟:

讓你的類繼承某個接口(該接口繼承自 ReflectObject 類)編寫一個對應的工廠類,并實例化一個工廠類對象調用反射器的 registerFactory 接口,將你的類名和工廠類對象保存到反射器中

特別的,上述第 2 和 3 步很明顯是屬于成年不變的步驟,它可以使用宏函數來實現。在你完成步驟 1 后,就可以使用宏函數一次完成。在這里,將步驟2 和 3 統一稱為“注冊反射類”。

2.5 注冊反射類

注冊反射類實際上就是 2.4 中的第 2 和 3 步,其代碼如下:

步驟 1:定義 Allen 類(略)步驟 2:定義 Allen 的工廠類class ObjectFactory_Allen : public ObjectFactory{ ReflectObject* newInstance(){ return new Allen(); };}步驟 3:創建 Allen 工廠類實例對象并注冊到反射器中// 函數 reflector 可以用來獲取反射器對象。reflector().registerFactory("Allen", new ObjectFactory_Allen());

為了能讓上面的代碼復用,使用宏函數來進行改寫:

/***********需要被反射的類,需要在其對應的 cpp 文件中進行反射聲明***********/#define REFLECT(name)/class ObjectFactory_##name : public ObjectFactory{/public:/ ReflectObject* newInstance() {/ return new name(); / }/}; /class Register_##name{/public:/ Register_##name(){/ reflector().registerFactory(#name, new ObjectFactory_##name()); / }/};/Register_##name register_##name;

這樣,以后步驟 2 和 步驟 3 就可以簡寫成:

REFLECT(Allen);

看起來是不是很方便?

上面的宏函數并沒有直接調用反射器的注冊函數,而是先定義了一個注冊類對象,在注冊類對象的構造函數中完成了調用,然后又定義了一個該類的全局對象,以達到自動調用構造函數的目的。想一想,為什么不直接調用反射器的注冊函數?

3. 完整示例

3.1 客戶端部分

main 函數#include "Person.h"#include "Reflector.h"int _tmain(int argc, _TCHAR* argv[]){ Person *allen = getNewInstance<Person>("Allen"); Person *luffy = getNewInstance<Person>("Luffy"); allen->show(); luffy->show(); delete allen; delete luffy; return 0;}用戶編寫的 Allen 類和 Luffy 類#include "Person.h"class Allen : public Person{public: Allen() virtual ~Allen(); virtual void show();};class Luffy : public Person{public: Luffy(); virtual ~Luffy(); virtual void show();};//兩個類的實現,在 cpp 文件中REFLECT(Allen);// 注冊反射類,只能寫在 cpp 文件中。Allen::Allen(){ std::cout << "Allen()" << std::endl;}Allen::~Allen(){ std::cout << "~Allen()" << std::endl;}void Allen::show(){ std::cout << "Hello, I'm Allen" << std::endl;}REFLECT(Luffy); // 注冊反射類,只能寫在 cpp 文件中。Luffy::Luffy(){ std::cout << "Luffy()" << std::endl;}Luffy::~Luffy(){ std::cout << "~Luffy()" << std::endl;}void Luffy::show(){ std::cout << "Hello, I'm Luffy" << std::endl;}

3.2 框架部分

Person 接口定義與實現// Person.h#include "Reflector.h"http:// 讓 Person 繼承反射基類class Person : public ReflectObject{public: Person(); virtual ~Person(); virtual void show();};// Person.cppPerson::Person(){ std::cout << "Person()" << std::endl;}Person::~Person(){ std::cout << "~Person()" << std::endl;}void Person::show(){ std::cout << "Hello, I'm person" << std::endl;}反射器部分// Reflect.h#pragma once#include <string>#include <map>#include <iostream>/********************所有需要實現反射的類需要繼承它************************/class ReflectObject { public: virtual ~ReflectObject(){}};/************************************************************************//******************對象工廠抽象類,用來生成對象實例************************/class ObjectFactory {public: ObjectFactory(){ std::cout << "ObjectFactory()" << std::endl; } virtual ~ObjectFactory(){ std::cout << "~ObjectFactory()" << std::endl; } virtual ReflectObject* newInstance() = 0;};/************************************************************************//***********反射器,用來管理(對象名,對象工廠)的映射關系******************/class Reflector{public: Reflector(); ~Reflector(); void registerFactory(const std::string& className, ObjectFactory *of); ReflectObject* getNewInstance(const std::string& className);private: std::map<std::string, ObjectFactory*> objectFactories;};/************************************************************************//**********************獲取反射器實例,全局唯一****************************/Reflector& reflector();/************************************************************************//***********需要被反射的類,需要在其對應的 cpp 文件中進行反射聲明***********/#define REFLECT(name)/class ObjectFactory_##name : public ObjectFactory{/public:/ ObjectFactory_##name(){ std::cout << "ObjectFactory_" << #name << "()" << std::endl; }/ virtual ~ObjectFactory_##name(){ std::cout << "~ObjectFactory_" << #name << "()" << std::endl; }/ ReflectObject* newInstance() {/ return new name(); / }/}; /class Register_##name{/public:/ Register_##name(){/ reflector().registerFactory(#name, new ObjectFactory_##name()); / }/};/Register_##name register_##name;/************************************************************************//***********************根據類名獲取對象實例******************************/template<typename T>T* getNewInstance(const std::string& className) { return dynamic_cast<T*>(reflector().getNewInstance(className));}/************************************************************************/// Reflector.cpp#include "Reflector.h"Reflector::Reflector(){}Reflector::~Reflector(){ std::map<std::string, ObjectFactory*>::iterator it = objectFactories.begin(); for (; it != objectFactories.end();++it) { delete it->second; } objectFactories.clear();}void Reflector::registerFactory(const std::string& className, ObjectFactory *of){ std::map<std::string, ObjectFactory*>::iterator it = objectFactories.find(className); if (it != objectFactories.end()) { std::cout << "該類已經存在……" << std::endl; } else { objectFactories[className] = of; }}ReflectObject* Reflector::getNewInstance(const std::string& className){ std::map<std::string, ObjectFactory*>::iterator it = objectFactories.find(className); if (it != objectFactories.end()) { ObjectFactory *of = it->second; return of->newInstance(); } return NULL;}// 用來獲取反射器對象,注意這是全局唯一的。Reflector& reflector() { static Reflector reflector; return reflector;}

3.3 運行結果

這里寫圖片描述

4. 總結

反射機制的實現,主要在于工廠模式的靈活使用。另外,還需要掌握一些 C++ 代碼技巧,比如如何在 main 函數之前進行初始化操作,反射器的初始化以及生產工廠類對象很好的體現了全局對象的應用。

理解多態,接口,繼承掌握對象工廠的使用方法掌握工廠模式理解反射器的工作原理掌握宏函數的編寫代碼下載:http://git.oschina.net/ivan_allen/Reflection
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表

圖片精選

亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
久久激情视频免费观看| 18一19gay欧美视频网站| 色综合久久悠悠| 国产成人综合一区二区三区| 亚洲天堂av在线播放| 久久精品国产精品| 亚洲欧美一区二区三区四区| 岛国av午夜精品| 欧美成人午夜激情在线| 岛国视频午夜一区免费在线观看| 538国产精品一区二区免费视频| 日韩一中文字幕| 午夜精品久久久久久久白皮肤| 成人福利免费观看| 欧美与欧洲交xxxx免费观看| 高潮白浆女日韩av免费看| 亚洲摸下面视频| 性欧美长视频免费观看不卡| 欧美日韩亚洲精品内裤| 国产一区二区香蕉| 国产精品欧美日韩久久| 亚洲午夜未满十八勿入免费观看全集| 国产日产欧美精品| 亚洲第一男人av| 成人久久久久爱| 亚洲精品一区中文字幕乱码| 日韩中文娱乐网| 97国产真实伦对白精彩视频8| 夜夜嗨av色一区二区不卡| 亚洲无线码在线一区观看| 亚洲国产精品一区二区久| 国内精品久久久久久中文字幕| 久久精品电影一区二区| 成人观看高清在线观看免费| 国产精品吊钟奶在线| 91精品国产777在线观看| 日韩一区二区久久久| 亚洲成人网在线观看| 亚洲免费一级电影| 久久精品国亚洲| 中文字幕在线看视频国产欧美| 日本高清+成人网在线观看| 国产精品美女午夜av| 亚洲欧美日韩国产中文专区| 成人免费网站在线观看| 国产成人av在线播放| 一区二区亚洲精品国产| 日韩高清人体午夜| 91免费在线视频| 青青草原成人在线视频| 国内精品久久久久影院 日本资源| 亚洲bt欧美bt日本bt| 国产精品网红直播| 欧美黑人国产人伦爽爽爽| 国产精品麻豆va在线播放| 2018国产精品视频| 国产精品自拍偷拍| 久久精品亚洲国产| 亚洲综合视频1区| 正在播放欧美一区| 一区二区在线视频播放| 亚洲国产又黄又爽女人高潮的| 欧美日韩国产麻豆| www.欧美视频| 久久久久久国产精品三级玉女聊斋| 日韩精品免费在线视频| 热久久美女精品天天吊色| 欧美成人免费大片| 欧美激情在线狂野欧美精品| 亚洲精品黄网在线观看| 91在线免费网站| 97在线视频免费观看| 亚洲第一级黄色片| 精品视频在线播放| 欧美一乱一性一交一视频| 国产一区二区丝袜高跟鞋图片| 久久精品成人欧美大片| 欧美性极品少妇精品网站| 亚洲香蕉成视频在线观看| 亚洲成人黄色在线观看| 欧美精品18videos性欧| 91深夜福利视频| 久久777国产线看观看精品| 日韩视频在线免费观看| 国产精品入口免费视频一| 欧美另类99xxxxx| 91免费精品国偷自产在线| 亚洲免费av电影| 国产精品美女久久| 国产激情999| 欧美多人乱p欧美4p久久| 国产v综合ⅴ日韩v欧美大片| 欧美与黑人午夜性猛交久久久| 久久综合色影院| 国产成人精品日本亚洲| 最近2019中文字幕一页二页| 九九热最新视频//这里只有精品| 欧美成aaa人片免费看| 亚洲天堂免费观看| 日韩精品极品视频免费观看| 成人xxxx视频| 5566成人精品视频免费| 亚洲日本中文字幕| 免费不卡欧美自拍视频| 日韩成人免费视频| 理论片在线不卡免费观看| 欧美性猛交丰臀xxxxx网站| 国产精品久久久av| 92看片淫黄大片欧美看国产片| 亚洲精品免费在线视频| 亚洲xxxxx性| 日韩在线激情视频| 国产精品高潮粉嫩av| 日本中文字幕久久看| 欧美激情国产精品| 日韩影视在线观看| 久久精品久久久久电影| 亚洲欧洲偷拍精品| 欧美肥婆姓交大片| 在线日韩精品视频| 久久视频在线观看免费| 久久久国产在线视频| 欧美怡红院视频一区二区三区| 国产精品入口免费视| 国产精品日韩专区| 欧美日韩午夜激情| 日韩欧美一区二区三区| 色婷婷av一区二区三区在线观看| 青草热久免费精品视频| 日韩国产一区三区| 欧美视频国产精品| 久久久久久国产精品三级玉女聊斋| 亚洲精品suv精品一区二区| 亚洲人午夜精品| 国产精品久久久久久久美男| 欧美在线影院在线视频| 精品国产户外野外| 亚洲三级av在线| 欧美在线视频观看免费网站| 亚洲国产日韩欧美在线图片| 午夜精品一区二区三区视频免费看| 亚洲国产日韩欧美在线99| 日韩女在线观看| 国产精品久久久久久av下载红粉| 亚洲综合视频1区| 国产欧美日韩亚洲精品| 原创国产精品91| 国内精品国产三级国产在线专| 欧美丝袜一区二区三区| www.欧美三级电影.com| 最近2019好看的中文字幕免费| 国产欧美日韩精品丝袜高跟鞋| 91精品国产精品| 成人精品视频99在线观看免费| 日韩成人av网| 亚洲毛茸茸少妇高潮呻吟| 欧美精品一区二区三区国产精品| 日韩在线中文字| 欧美一级在线亚洲天堂| 欧美高清在线视频观看不卡| 久久亚洲国产成人| 欧美日韩一区二区免费在线观看| 久久夜色精品国产亚洲aⅴ| 日韩av在线一区|