C++語言動態創建對象


  焦頭爛額的考試月終於過去了,終於有時間能停下來思考記錄一下這一個月學過的東西,首先先總結一下,在自己仿寫魂斗羅游戲時遇見的問題之一,人物在移動的時候如何去判斷什么時候掉入水中顯示水中畫面,什么時候敵人該開槍,這個時候我使用了一堆數字來描述地圖,如圖

但是在代碼實現時,就得用一大堆判斷,來判斷何時應該創建對象來調用成員函數,其代碼繁雜不說,更加降低了代碼的復用性,如果我想在其中添加功能,還得再修改代碼,這個時候我就想到了動態創建數組這個東西,根據我輸入的數字長度,數組可以自動去增長,那對象是不是可以動態的去創建呢?,可能是我搜索的有問題,在網上很少有介紹這方面的過程,我覺得還是有必要記錄一下,給其他人也提供一個借鑒

首先先用字符串去做一個實驗,添加三個類,我想通過輸入一個字符串就能創建相應的對象,此時就需要一系列判斷

1     char pStr[20] = {0};
2     cin >> pStr;
3     if(strcmp(pStr,"AAAA") == 0)
4         AAAA *p =  new AAAA;
5     if(strcmp(pStr,"BBBB") == 0)
6         BBBB *p =  new BBBB;
7     if(strcmp(pStr,"DDDD") == 0)
8         DDDD *p =  new DDDD;

這個時候就會出現我遇到的情況,代碼繁雜,降低復用性,首先修改的就是創建對象,據說好的程序員不會寫出來毀滅地球的代碼,而是寫一個毀滅行星的函數,把地球當作參數傳進去

 1 void CreateObjectAAAA()
 2 {
 3     AAAA *p =  new AAAA;
 4 }
 5 void CreateObjectBBBB()
 6 {
 7     BBBB *p =  new BBBB;
 8 }
 9 void CreateObjectDDDD()
10 {
11     DDDD *p =  new DDDD;
12 }
13 int main()
14 {
15     char pStr[20] = {0};
16     cin >> pStr;
17     if(strcmp(pStr,"AAAA") == 0)
18         CreateObjectAAAA();
19     if(strcmp(pStr,"BBBB") == 0)
20         CreateObjectBBBB();
21     if(strcmp(pStr,"DDDD") == 0)
22         CreateObjectDDDD();

然后如何能動態創建呢,可以想到鏈表可以實現動態的創建,但是創建對象無法用鏈表來表示,但可以將字符串,創建對象的函數指針打包成一個結點,只要輸入字符串,就可以遍歷鏈表實現創建了

1 struct Node
2 {
3     char pStr[20];
4     void (*pfnCreateObject)();
5     Node* pNext;
6 };

但現在問題是如何實現普適性,比如直接在類里貼一個宏,之后不用再創建對象了

首先是統一結點,由於在創建對象之后需要使用對象,創建對象函數return的值也都不一樣,這樣的話,結點里的函數指針的類型也不一樣了,統一結點的方法就是利用父類指針指向子類對象,為這些類創建一個父類,這個函數指針直接定義為父類即可

 1 struct Node
 2 {
 3     char pStr[20];
 4     COObject* (*pfnCreateObject)();
 5     Node* pNext;
 6 };
 7 COObject* CreateObjectAAAA()
 8 {
 9     AAAA *p =  new AAAA;
10     return p;
11 }
12 COObject* CreateObjectBBBB()
13 {
14     BBBB *p =  new BBBB;
15     return p;
16 }
17 COObject* CreateObjectDDDD()
18 {
19     DDDD *p =  new DDDD;
20     return p;
21 }

 

接下來用宏代替每個類里的什么東西呢,換句話說哪些東西需要寫到類內呢?

結構體,遍歷匹配,放在父類中

 1 #pragma once
 2 class COObject;
 3 struct Node
 4 {
 5     char pStr[20];
 6     COObject* (*pfnCreateObject)();
 7     Node* pNext;
 8 };
 9 class COObject
10 {
11 public:
12     COObject(void);
13     virtual ~COObject(void);
14 public:
15     COObject *Create(const char *pszClassName);
16 };
 1 #include "OObject.h"
 2 #include<string.h>
 3 
 4 COObject::COObject(void)
 5 {
 6 }
 7 
 8 
 9 COObject::~COObject(void)
10 {
11 }
12 COObject *COObject::Create(const char *pszClassName)
13 {
14     Node *pTemp = 0;
15     while(pTemp)
16     {
17         if(strcmp(pTemp->pStr,pszClassName) == 0)
18         {
19             return pTemp->pfnCreateObject();
20         }
21         pTemp = pTemp->pNext;
22     }
23     return 0;
24 }

而每一個子類中則放入創建結點,創建對象函數,其中有一點尤為注意,因為此時並未創建對象,所以這里的成員函數都是靜態成員

 1 #pragma once
 2 #include"OObject.h"
 3 class AAAA : public COObject
 4 {
 5 public:
 6     AAAA(void);
 7     ~AAAA(void);
 8 public:
 9     static Node node;
10     static COObject*CreateObject();
11 };
 1 #include "AAAA.h"
 2 Node AAAA::node = {"AAAA",0,&AAAA::CreateObject};
 3 COObject*AAAA::CreateObject()
 4 {
 5     return new AAAA;
 6 }
 7 
 8 AAAA::AAAA(void)
 9 {
10 }
11 
12 
13 AAAA::~AAAA(void)
14 {
15 }

每個類都如此,但是當我實際操作的時候,程序卻崩了,調試后發現,在遍歷中,我每加一個結點就得修改一此頭結點,那我寫上面這些的意義就不存在了,都是添加還不如一大堆if看起來邏輯清晰呢,最后通過一個辦法可以解決,由於在函數之外不允許調用函數,除了一個,那就是構造函數,我在父類中又定義了一個專門添加的類,在這個類的構造里我把添加的結點傳進去,進行頭結點的更替,在遍歷中始終從頭節點開始遍歷。那么在以后的編程中,如果我不知道何時該創建對象的話,在類的頭文件和實現中就可以分別貼上這兩個宏,再繼承一個COObject的接口類即可。

 1 #define DECLEAR_DYNCREATE()\ 2 static Node node;\ 3 static COObject*CreateObject(); 

1 #define IMPLEMENT_DYNCREATE(ThisClass)\
2     Node ThisClass::node = {#ThisClass,0,&ThisClass::CreateObject};\
3     InitObject init##ThisClass(&ThisClass::node);\
4     COObject* ThisClass::CreateObject()\
5     {\
6         return new ThisClass;\
7     }

 

 

2019-06-23 14:17:33 編程小菜鳥自我反思,大家可以留下自己的意見和建議,謝謝!!!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM