/*********************************************************************************************************************
* 發布日期:2017-11-13 16:23:44
* 進度:
* 作者:LuoTian
* 備注:動態創建
*********************************************************************************************************************/
這一篇承接上一篇的運行時類型識別,當各個類像鏈表一樣串接之后,做各種功能就比較簡單。
動態創建的思路:
動態創建就是指輸入一個類名就能創建一個對象,比如在控制台中輸入Base,就能創建Base類的對象。
假設有三個類Base,B,C,繼承關系為Base<-B<-C,其中Base為根類。根據上一篇所寫,將這三個類通過CRuntimeClass進行串接。因為動態創建需要這個,原因容易理解,假如你輸入一個Base,程序則必須根據輸入的這個字符串在鏈接的類中查找是否存在Base這個類,於是就需要遍歷,從C開始一直查找到Base。
為了實現這些功能,除了在CRuntimeClass里面再添加一些信息之外,還在能動態創建的類中添加一個靜態函數CreateObject( );
流程如下:
假定輸入Base,程序根據pFirst從尾端開始遍歷各個類,查找是否有類名=Base的類,如果不存在則程序返回。如果存在,再看它的一個字段m_pfnCreateObject是否為空,而這個m_pfnCreateObject是一個函數指針,所指向的就是在能動態創建的類中添加的靜態函數CreateObject(),假如一個類不能動態創建,那么肯定沒有這個CreateObject函數,則在初始化CRuntimeClass的時候,m_pfnCreateObject也就為NULL了,如果能動態創建,m_pfnCreateObject就指向了CreateObject( ),然后通過m_pfnCreateObject指針執行函數調用。
思路總結:
一、能動態創建的類中有CreateObject()函數。
二、能動態創建的類的CRuntimeClass結構中的m_pfnCreateObject字段初賦值為CreateObjec,如果為NULL,則不具備動態創建的能力。
//實現比較簡單,直接new一個對象返回; static Base * PASCAL CreateObject(){return new B;}
示例代碼如下:
#include <iostream> using namespace std; #define PASCAL _stdcall class Base; /***************核心的CRuntimeClass結構********************/ struct CRuntimeClass { char * name; //類名 int ClassSize; //類大小; Base *(PASCAL * m_pfnCreateObject)(); CRuntimeClass *pBase;//基類的CRuntimeClass地址 Base * CreateObject(); static CRuntimeClass * PASCAL Load(); static CRuntimeClass *pFirst; CRuntimeClass *pNext; }; CRuntimeClass * CRuntimeClass::pFirst=NULL;//pFirst初始化為空; CRuntimeClass* PASCAL CRuntimeClass::Load() { char szClassName[64]; CRuntimeClass* pClass; cout << "輸入需要動態創建的類名:"; cin >> szClassName; //在各個類的CRuntimeClass結構中查找是否存在輸入的類名 for (pClass = pFirst; pClass != NULL; pClass = pClass->pNext) { if (strcmp(szClassName, pClass->name) == 0) return pClass; } cout<<"沒有找到該類名,程序退出!!"<<endl; return NULL; } Base * CRuntimeClass::CreateObject() { if (m_pfnCreateObject == NULL) { cout<<"不能動態創建!!"<<endl; return NULL; } else { Base * pObject =(*m_pfnCreateObject)(); return pObject; } } //****************結束*****************************************/ struct AFX_CLASSINIT { AFX_CLASSINIT(CRuntimeClass *pNewClass) { pNewClass->pNext=CRuntimeClass::pFirst; CRuntimeClass::pFirst=pNewClass; } }; class Base //根基類; { public: static CRuntimeClass classBase; virtual CRuntimeClass * GetRuntimeClass()const { return &Base::classBase; } virtual void SayHello() { cout<<"基類Base的SayHello"<<endl; } }; class B:public Base //B類 { public: static CRuntimeClass classB; static Base * PASCAL CreateObject(){return new B;} virtual CRuntimeClass * GetRuntimeClass()const{ return &B::classB; } virtual void SayHello(){ cout<<"類B的SayHello,動態創建對象成功!!"<<endl;} }; class C:public B //C類 { public: static CRuntimeClass classC; virtual CRuntimeClass * GetRuntimeClass()const{ return &C::classC; } }; //***********************實現部分*************************// struct CRuntimeClass Base::classBase={"Base",sizeof(Base),NULL,NULL}; static AFX_CLASSINIT _init_A(&Base::classBase);//② struct CRuntimeClass B::classB={"B",sizeof(B),B::CreateObject,&Base::classBase,}; static AFX_CLASSINIT _init_B(&B::classB);//③ struct CRuntimeClass C::classC={"C",sizeof(C),NULL,&B::classB,}; static AFX_CLASSINIT _init_C(&C::classC);//④ int main(int argc,char *argv[]) { CRuntimeClass * pClassRef; Base *pOb; cout<<"共有三個類Base,B,C,其中B類具有動態創建能力... ."<<endl; while(true) { if((pClassRef=CRuntimeClass::Load())==NULL) break; pOb=pClassRef->CreateObject(); if(pOb!=NULL) pOb->SayHello(); } return 0; }
