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

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

C++ 反射機制詳解及實例代碼

2020-05-23 13:53:43
字體:
來源:轉載
供稿:網友

C++ 反射機制

一.前言:

Java有著一個非常突出的動態相關機制:Reflection,用在Java身上指的是我們可以于運行時加載、探知、使用編譯期間完全未知的classes。換句話說,Java程序可以加載一個運行時才得知名稱的class,獲悉其完整構造(但不包括methods定義),并生成其對象實體、或對其fields設值、或喚起其methods。然而C++是不支持反射機制,雖然C++有RTTI(運行時類型識別)。但是想要實現C++對象序列化,序列化就是存儲到磁盤上,將對象變成一定格式的二進制編碼,然后要用的時候再將保存在磁盤上的二進制編碼轉化成一個內存中的對象,這個過程中總是需要有一個指示來告訴編譯器要生成什么樣的對象,最簡單的方式當然就是類名了,例如:將一個ClassXXX對象存儲到磁盤上,再從磁盤讀取的時候讓編譯器根據“ClassXXX”名稱來new一個對象。

ClassT* obj = FactoryCreate("ClassT"); 

類似于以上的語法,雖然C++沒有自帶的語法可以實現,但是我們可以自己通過其他方法來實現。(由于本人能力有限,所以該篇博客只是講解如何簡單的實現這個反射機制,而對C++中擁有這個反射機制是否有必要不做任何討論。當然,如果博客中有什么地方說的有錯誤還望大家可以在下面評論指出謝謝)

二.實現:

1.我們很容易可以想到可以使用簡單工廠模式來實現這個效果:比如

class Object { public:   virtual string ToString() = 0; }; 

這個是所有需要實現反射機制的類需要繼承的基類,然后派生出來的類只需要再實現這個ToString即可。例如:

class MyClass :public Object { public:   virtual string ToString(){ return "MyClass"; } }; 

然后就是用于產生對象的工廠。

Object* FactoryCreat(const string& className) {   if (className == "ClassA")     return new ClassA;   else if (className == "ClassB")     return new ClassB;   else if(className == "ClassC")     return new ClassC;   else if(className == "ClassD")     return new ClassD;   else if(className == "ClassE")     return new ClassE;   ... } 

我們使用就可以這樣:

int main() {   Object* obj = FactoryCreat("MyClass");   cout << obj->ToString();   delete obj;   return 0; } 

我們使用簡單工廠模式感覺好像是解決了問題,可以實現用字符串去new一個對應的對象,但是假如我們要新建一個類或者修改一個類,那么這個FactoryCreat都要進行修改。十分不利于維護。所以我們需要換一個方式來處理。

2.工廠模式結合回調機制。

首先我們要梳理一下這個方法的基本脈絡:

1.工廠內部需要有個映射,也就是一個字符串對應一個類new的方法。
2.工廠給出一個接口,我們傳入字符串,那么返回這個字符串對應的方法new出來的對象指針。
3.我們新建的類,如果需要支持反射機制,那么這個類需要自動將自己的new方法和名字注冊到工廠的映射中。

OK,如果我們能完成以上幾個要求,那么我們在類進行拓展的時候需要改動的地方就十分少了。對于工廠的代碼我們基本上是不會改變的。也就基本上實現了我們C++反射機制的基本功能。

下面我們來一步一步解析代碼:

首先我們還是需要一個Object作為需要支持反射機制類的基類

//Reflex.h class Object { public:   Object(){}   virtual ~Object(){}   static bool Register(ClassInfo* ci);     //注冊傳入一個classInfo(類信息),將這個類的信息注冊到映射中   static Object* CreateObject(string name);   //工廠生產對象的接口 }; 

然后是實現:

//Reflex.cpp static std::map< string, ClassInfo*> *classInfoMap = NULL; bool Object::Register(ClassInfo* ci) {   if (!classInfoMap)  {     classInfoMap = new std::map< string, ClassInfo*>();   //這里我們是通過map來存儲這個映射的。   }   if (ci) {     if (classInfoMap->find(ci->m_className) == classInfoMap->end()){       classInfoMap->insert(std::map< string, ClassInfo*>::value_type(ci->m_className, ci)); // 類名 <-> classInfo     }   }   return true; } Object* Object::CreateObject(std::string name) {   std::map< string, ClassInfo*>::const_iterator iter = classInfoMap->find(name);   if (classInfoMap->end() != iter) {     return iter->second->CreateObject();     //當傳入字符串name后,通過name找到info,然后調用對應的CreatObject()即可   }   return NULL; } 

剩下的我們還需要一個classinfo類就大功告成了:

//Reflex.h  typedef Object* (*ObjectConstructorFn)(void); class ClassInfo { public:   ClassInfo(const std::string className, ObjectConstructorFn ctor)     :m_className(className), m_objectConstructor(ctor)   {     Object::Register(this);       //classInfo的構造函數是傳入類名和類對應的new函數然后自動注冊進map中。   }   virtual ~ClassInfo(){}   Object* CreateObject()const { return m_objectConstructor ? (*m_objectConstructor)() : 0; }   bool IsDynamic()const { return NULL != m_objectConstructor; }   const std::string GetClassName()const { return m_className; }   ObjectConstructorFn GetConstructor()const{ return m_objectConstructor; } public:   string m_className;   ObjectConstructorFn m_objectConstructor; }; 

有了這些類后,我們只需要讓需要支持反射的類滿足以下要求即可:

1.繼承Object類。
2.重載一個CreatObject()函數,里面 return  new 自身類。
3.擁有一個classInfo的成員并且用類名和CreatObject初始化。

滿足以上三個要求的類我們就可以利用反射機制來創建對象了。我們可以看下面的例子:

class B : public Object { public:   B(){ cout << hex << (long)this << " B constructor!" << endl; }   ~B(){ cout << hex << (long)this << " B destructor!" << endl; }   virtual ClassInfo* GetClassInfo() const{ return &ms_classinfo; }   static Object* CreateObject() { return new B; } protected:   static ClassInfo ms_classinfo; }; ClassInfo B::ms_classinfo("B", B::CreateObject); 

使用的話我們就只需要調用Object::CreatObject(string) 傳入類名即可。

int main() {   Object* obj = Object::CreateObject("B");   delete obj;   return 0; } 

基本上反射機制的功能就實現了,而且使用回調注冊在后期拓展上也容易維護。

三.使用宏簡化代碼:

其實大家發現,因為我們要讓類支持反射那么就要滿足我們上面的那三個要求,但是每個類都要寫這樣相似的東西。仔細一看,包括函數申da's明、函數定義、函數注冊,每個類的代碼除了類名外其它都是一模一樣的,有沒有簡單的方法呢?
那就是使用宏。

//Reflex.h  //類申明中添加 classInfo 屬性 和 CreatObject、GetClassInfo 方法 #define DECLARE_CLASS(name) /   protected: /     static ClassInfo ms_classinfo; /   public: /     virtual ClassInfo* GetClassInfo() const; /     static Object* CreateObject();  //實現CreatObject 和 GetClassInfo 的兩個方法 #define IMPLEMENT_CLASS_COMMON(name,func) /   ClassInfo name::ms_classinfo((#name), /        (ObjectConstructorFn) func); /              /   ClassInfo *name::GetClassInfo() const /     {return &name::ms_classinfo;}  //classInfo 屬性的初始化 #define IMPLEMENT_CLASS(name)      /   IMPLEMENT_CLASS_COMMON(name,name::CreateObject) /   Object* name::CreateObject()          /     { return new name;} 

有了宏替換后,我們定義一個新的類。

只需要在類定義中添加 DECLARE_CLASS(classname) 實現中添加IMPLEMENT_CLASS(classname)就可以讓這個類實現反射了。

例如我們上面的類B就可以這樣寫:

class B : public Object {   DECLARE_CLASS(B) public:   B(){ cout << hex << (long)this << " B constructor!" << endl; }   ~B(){ cout << hex << (long)this << " B destructor!" << endl; } }; IMPLEMENT_CLASS(B) 

這樣不管以后需要添加、修改什么功能都只需要修改宏就可以了而不需要每個類每個類去添加、修改方法。

ok到這里基本上,c++反射機制的實現就大功告成了!。

感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
这里只有精品丝袜| 91免费综合在线| 色噜噜久久综合伊人一本| 国产精品视频永久免费播放| 久久影院资源网| 日韩中文字幕在线免费观看| 久久成人综合视频| 久久久视频精品| 精品视频在线导航| 永久免费精品影视网站| 欧美日韩人人澡狠狠躁视频| 成人黄色在线免费| 欧美刺激性大交免费视频| 国产视频久久久久| 欧美在线免费视频| 91免费在线视频| 亚洲大胆人体在线| 8090理伦午夜在线电影| 欧美丰满少妇xxxxx| 欧美一区二区三区四区在线| 欧美孕妇孕交黑巨大网站| 欧美丰满老妇厨房牲生活| 成人免费直播live| 欧美性极品xxxx娇小| 81精品国产乱码久久久久久| 2021国产精品视频| 欧美一级电影免费在线观看| 不卡中文字幕av| 97人人爽人人喊人人模波多| 日韩电影在线观看中文字幕| 按摩亚洲人久久| 成人午夜激情免费视频| 亚洲自拍偷拍在线| 久久久久久综合网天天| 久久av.com| 国产成人高潮免费观看精品| 久久精品精品电影网| 久久视频在线视频| 精品日韩视频在线观看| 2021国产精品视频| 色琪琪综合男人的天堂aⅴ视频| 精品偷拍各种wc美女嘘嘘| 黑人狂躁日本妞一区二区三区| 亚洲午夜精品久久久久久久久久久久| 欧美午夜精品伦理| 亚洲精品在线观看www| 亚洲性无码av在线| 亚洲人线精品午夜| 亚洲自拍小视频| 欧美激情精品久久久久久大尺度| 国产精品旅馆在线| 亚洲夜晚福利在线观看| 亚洲欧美日韩第一区| 亚洲一品av免费观看| 欧美亚洲日本网站| 久久精品亚洲94久久精品| 久久精品免费电影| 久久夜色精品亚洲噜噜国产mv| 亚洲一区二区日本| 国产精品视频1区| 久久久国产在线视频| 欧洲日韩成人av| 91人人爽人人爽人人精88v| 日韩电影免费在线观看| 色婷婷综合久久久久中文字幕1| 精品精品国产国产自在线| 久久精彩免费视频| 亚洲国产私拍精品国模在线观看| 综合激情国产一区| 久久久中精品2020中文| 欧美一区二区大胆人体摄影专业网站| 黑人巨大精品欧美一区二区| 黑人巨大精品欧美一区二区| 一区二区欧美日韩视频| 中文字幕av一区二区三区谷原希美| 国产极品精品在线观看| 亚洲一区二区三区xxx视频| 韩国19禁主播vip福利视频| 亚洲精品日韩久久久| 一区二区三区国产视频| 亚洲欧美国产日韩中文字幕| 91精品综合久久久久久五月天| 免费av一区二区| 午夜精品久久久久久久99热| 亚洲国产97在线精品一区| 亚洲影院污污.| 在线中文字幕日韩| 欧美疯狂做受xxxx高潮| 成人福利网站在线观看11| 亚洲国产精品成人一区二区| 国内精品久久久久久中文字幕| 亚洲国产精品久久久久| 国产成人精品日本亚洲| 精品欧美国产一区二区三区| 国外成人免费在线播放| 久久精品99久久久久久久久| 精品一区二区三区四区在线| 韩国三级电影久久久久久| 国产精品第七影院| 日韩电影在线观看中文字幕| 国产精品小说在线| 成人黄色大片在线免费观看| 亚洲综合在线小说| 国产精品电影观看| 日韩精品视频在线观看网址| 秋霞午夜一区二区| 88xx成人精品| 精品久久久久久国产91| 亚洲综合大片69999| 国产精品日日摸夜夜添夜夜av| 欧美国产日韩一区二区三区| 国产国语刺激对白av不卡| 国产91精品久久久久| 福利一区视频在线观看| 欧美精品在线免费观看| 日韩av免费观影| 精品性高朝久久久久久久| 情事1991在线| 国产精品视频一| 超碰97人人做人人爱少妇| 国产成人一区二区在线| 97在线免费观看视频| 美日韩精品免费观看视频| 97色在线视频| 国产成人av在线播放| 米奇精品一区二区三区在线观看| 4k岛国日韩精品**专区| 青青久久av北条麻妃海外网| 久久亚洲精品一区| 国产成人久久久精品一区| 日韩成人中文字幕在线观看| 91在线观看免费观看| 欧美一区二粉嫩精品国产一线天| 精品久久在线播放| 亚洲国产另类久久精品| 亚洲第一精品夜夜躁人人躁| 精品国产一区二区三区久久久狼| 欧美激情一区二区三区在线视频观看| 欧美激情视频免费观看| 国产精品久久久久久久久免费看| 亚洲综合精品伊人久久| 全色精品综合影院| 亚洲第一福利视频| 亚洲xxxx妇黄裸体| 国产视频在线一区二区| 揄拍成人国产精品视频| 亚洲国产精品悠悠久久琪琪| 日韩精品中文字幕在线播放| 91精品在线影院| 成人亚洲欧美一区二区三区| 日韩国产精品一区| 亚洲二区在线播放视频| 欧美在线一级视频| 成人欧美一区二区三区在线| 亚洲人成网站免费播放| 欧美一区二区三区……| 久久色精品视频| 国产精品视频久久久久| 国产一区视频在线播放| 午夜精品福利电影| 91视频国产一区| 久久久久久12| 欧美丝袜美女中出在线| 中文字幕亚洲无线码a|