zoukankan      html  css  js  c++  java
  • 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 编程小菜鸟自我反思,大家可以留下自己的意见和建议,谢谢!!!

  • 相关阅读:
    border-radius:50%和100%究竟有什么区别
    GoLang几种读文件方式的比较
    Golang Import使用入门
    golang: 常用数据类型底层结构分析
    Python--字典操作
    Python--字符串操作
    Python split 分割中文
    LR(逻辑回归)
    Python--列表操作
    Eclipse 使用Anaconda python 解释器
  • 原文地址:https://www.cnblogs.com/xgmzhna/p/11072731.html
Copyright © 2011-2022 走看看