C++中反射機(jī)制的示例分析-創(chuàng)新互聯(lián)

這篇文章給大家分享的是有關(guān)C++中反射機(jī)制的示例分析的內(nèi)容。小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考,一起跟隨小編過來看看吧。

白城ssl適用于網(wǎng)站、小程序/APP、API接口等需要進(jìn)行數(shù)據(jù)傳輸應(yīng)用場景,ssl證書未來市場廣闊!成為創(chuàng)新互聯(lián)公司的ssl證書銷售渠道,可以享受市場價(jià)格4-6折優(yōu)惠!如果有意向歡迎電話聯(lián)系或者加微信:18982081108(備注:SSL證書合作)期待與您的合作!

C++ 反射機(jī)制

一.前言:

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

ClassT* obj = FactoryCreate("ClassT");

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

二.實(shí)現(xiàn):

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

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

這個(gè)是所有需要實(shí)現(xiàn)反射機(jī)制的類需要繼承的基類,然后派生出來的類只需要再實(shí)現(xiàn)這個(gè)ToString即可。例如:

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

然后就是用于產(chǎn)生對(duì)象的工廠。

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

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

2.工廠模式結(jié)合回調(diào)機(jī)制。

首先我們要梳理一下這個(gè)方法的基本脈絡(luò):

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

OK,如果我們能完成以上幾個(gè)要求,那么我們?cè)陬愡M(jìn)行拓展的時(shí)候需要改動(dòng)的地方就十分少了。對(duì)于工廠的代碼我們基本上是不會(huì)改變的。也就基本上實(shí)現(xiàn)了我們C++反射機(jī)制的基本功能。

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

首先我們還是需要一個(gè)Object作為需要支持反射機(jī)制類的基類

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

然后是實(shí)現(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來存儲(chǔ)這個(gè)映射的。 
  } 
  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();     //當(dāng)傳入字符串name后,通過name找到info,然后調(diào)用對(duì)應(yīng)的CreatObject()即可 
  } 
  return NULL; 
}

剩下的我們還需要一個(gè)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的構(gòu)造函數(shù)是傳入類名和類對(duì)應(yīng)的new函數(shù)然后自動(dòng)注冊(cè)進(jìn)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.重載一個(gè)CreatObject()函數(shù),里面 return  new 自身類。
3.擁有一個(gè)classInfo的成員并且用類名和CreatObject初始化。

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

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

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

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

基本上反射機(jī)制的功能就實(shí)現(xiàn)了,而且使用回調(diào)注冊(cè)在后期拓展上也容易維護(hù)。

三.使用宏簡化代碼:

其實(shí)大家發(fā)現(xiàn),因?yàn)槲覀円岊愔С址瓷淠敲淳鸵獫M足我們上面的那三個(gè)要求,但是每個(gè)類都要寫這樣相似的東西。仔細(xì)一看,包括函數(shù)申da's明、函數(shù)定義、函數(shù)注冊(cè),每個(gè)類的代碼除了類名外其它都是一模一樣的,有沒有簡單的方法呢?
那就是使用宏。

//Reflex.h 
 
//類申明中添加 classInfo 屬性 和 CreatObject、GetClassInfo 方法 
#define DECLARE_CLASS(name) \ 
  protected: \ 
    static ClassInfo ms_classinfo; \ 
  public: \ 
    virtual ClassInfo* GetClassInfo() const; \ 
    static Object* CreateObject(); 
 
//實(shí)現(xiàn)CreatObject 和 GetClassInfo 的兩個(gè)方法 
#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;}

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

只需要在類定義中添加 DECLARE_CLASS(classname) 實(shí)現(xiàn)中添加IMPLEMENT_CLASS(classname)就可以讓這個(gè)類實(shí)現(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)

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

ok到這里基本上,c++反射機(jī)制的實(shí)現(xiàn)就大功告成了!。

感謝各位的閱讀!關(guān)于“C++中反射機(jī)制的示例分析”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,讓大家可以學(xué)到更多知識(shí),如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到吧!

另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)建站muchs.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場景需求。

標(biāo)題名稱:C++中反射機(jī)制的示例分析-創(chuàng)新互聯(lián)
URL鏈接:http://muchs.cn/article4/ddoeoe.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供Google、云服務(wù)器App設(shè)計(jì)、App開發(fā)、電子商務(wù)企業(yè)網(wǎng)站制作

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

外貿(mào)網(wǎng)站制作