最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

 更新時間:2017年01月20日 11:52:35   投稿:lqh  
這篇文章主要介紹了C++ 反射機制詳解及實例代碼的相關資料,需要的朋友可以參考下

C++ 反射機制

一.前言:

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

ClassT* obj = FactoryCreate("ClassT"); 

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

二.實現(xiàn):

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

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

這個是所有需要實現(xiàn)反射機制的類需要繼承的基類,然后派生出來的類只需要再實現(xiàn)這個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; 
} 

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

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

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

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

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

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

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

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

然后是實現(xiàn):

//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的構造函數(shù)是傳入類名和類對應的new函數(shù)然后自動注冊進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()函數(shù),里面 return  new 自身類。
3.擁有一個classInfo的成員并且用類名和CreatObject初始化。

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

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; 
} 

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

三.使用宏簡化代碼:

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

//Reflex.h 
 
//類申明中添加 classInfo 屬性 和 CreatObject、GetClassInfo 方法 
#define DECLARE_CLASS(name) \ 
  protected: \ 
    static ClassInfo ms_classinfo; \ 
  public: \ 
    virtual ClassInfo* GetClassInfo() const; \ 
    static Object* CreateObject(); 
 
//實現(xiàn)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) 實現(xiàn)中添加IMPLEMENT_CLASS(classname)就可以讓這個類實現(xiàn)反射了。

例如我們上面的類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++反射機制的實現(xiàn)就大功告成了!。

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

相關文章

  • C++實現(xiàn)掃雷游戲(控制臺不閃屏版)

    C++實現(xiàn)掃雷游戲(控制臺不閃屏版)

    這篇文章主要為大家詳細介紹了C++實現(xiàn)掃雷游戲,控制臺不閃屏版,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-03-03
  • C++ 異常的詳細介紹

    C++ 異常的詳細介紹

    這篇文章主要介紹了C++ 異常的詳細介紹的相關資料,希望通過本文大家能夠掌握C++異常的使用方法,需要的朋友可以參考下
    2017-09-09
  • Socket通信原理和實踐

    Socket通信原理和實踐

    本文詳細講解了Socket通信原理和實踐,文中通過示例代碼介紹的非常詳細。對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-01-01
  • C語言順序表的基本結構與實現(xiàn)思路詳解

    C語言順序表的基本結構與實現(xiàn)思路詳解

    順序表是用一段物理地址連續(xù)的存儲單元依次存儲數(shù)據元素的線性結構,一般情況下采用數(shù)組存儲。本文將通過示例為大家講解一下順序表的基本操作,需要的可以參考一下
    2023-02-02
  • C/C++實現(xiàn)快速排序算法的思路及原理解析

    C/C++實現(xiàn)快速排序算法的思路及原理解析

    這篇文章主要介紹了C/C++實現(xiàn)快速排序算法的思路及原理解析,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-01-01
  • C++ LeeCode題目:比特位計數(shù)和買賣股票的最佳時機

    C++ LeeCode題目:比特位計數(shù)和買賣股票的最佳時機

    這篇文章主要介紹了基于C語言計算比特位計數(shù)和買賣股票的最佳時機,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2021-07-07
  • wince程序防止創(chuàng)建多個實例實現(xiàn)互斥作用

    wince程序防止創(chuàng)建多個實例實現(xiàn)互斥作用

    什么時候用的互斥?當你的程序只允許同時打開一個的時候,就可以通過互斥來實現(xiàn),下面說的互斥,主要是針對防止程序創(chuàng)建多個實例這種情況來實現(xiàn)的
    2014-02-02
  • C++11 thread多線程編程創(chuàng)建方式

    C++11 thread多線程編程創(chuàng)建方式

    這篇文章主要介紹了C++11 thread多線程編程的相關知識,包括線程的創(chuàng)建方式結束方式及互斥鎖的實例代碼詳解,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-12-12
  • C語言實現(xiàn)串的順序存儲表示與基本操作

    C語言實現(xiàn)串的順序存儲表示與基本操作

    這篇文章主要為大家詳細介紹了C語言實現(xiàn)串的順序存儲表示與基本操作,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-09-09
  • C++?LeetCode1769移動所有球到每個盒子最小操作數(shù)示例

    C++?LeetCode1769移動所有球到每個盒子最小操作數(shù)示例

    這篇文章主要為大家介紹了C++?LeetCode1769移動所有球到每個盒子所需最小操作數(shù)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-12-12

最新評論

友谊县| 屏南县| 本溪市| 武冈市| 香格里拉县| 彭阳县| SHOW| 东台市| 博野县| 房产| 阿瓦提县| 平泉县| 弥渡县| 泸州市| 翁源县| 明水县| 甘谷县| 平邑县| 阿勒泰市| 南充市| 阜新市| 大方县| 吴江市| 乌鲁木齐市| 青海省| 盐池县| 涿鹿县| 汝阳县| 体育| 枣阳市| 荥经县| 车险| 依兰县| 茶陵县| 宁陕县| 开鲁县| 崇仁县| 华宁县| 四川省| 荔波县| 白玉县|