0

我正在为简单的类 Rogue 游戏制作一张简单的地图。因此,我需要通过从字符数组 [i] [j] 接收数据,使用为每个数组单元创建的对象来初始化映射。建议这样的 CWall、CDoor 类在其他文件中定义,如 CWall.cpp、CWall.h,下面是 map.cpp 中初始化的代码

但这是正确的编码方式吗?我认为这会导致分配内存的问题。

CObject CMap::insertObject(char character){ 
    if (character = '*') {
        CWall cwall;
        return cwall;
    }

    if (character = 'D') {
        CDoor cdoor;
        return cdoor;
    }

    if (character = 'F') {
        CFood cfood;
        return cfood;
    }

    if (character = 'K') {
        CKey ckey;
        return ckey;
    }

    if (character = 'M') {
        CMMonster cmmonster;
        return cmmonster;
    }

    if (character = 'm') {
        CMonster cmonster;
        return cmonster;
    }

    if (character = '@') {
        CPlayer cplayer;
        return cplayer;
    }

    if (character = 'P') {
        CPrincess cprincess;
        return cprincess;
    }

    if (character = '&') {
        CRock crock;
        return crock;
    }

    if (character = 'S') {
        CShield cshield
        return cshield;
    }

    else {
        CShield cshield;
        return cshield;
    }
}

void CMap::initialize(char arr[][COLS]){
    for (int i = 0; i <= 11; i++){
        for (int j = 0; j <= 38; j++){
            char character = arr[i][j];
            insertObject(character);
        }
    }
}
4

4 回答 4

3

这不是正确的做法。你会受到对象切片的影响,因为我猜你CObject是一个对象而不是指向某个对象的指针。您需要CObject*在函数中返回一个类型的指针,然后为每种情况返回一个new CMonsternew CPlayer等。更好的是,改用智能指针。

您尝试实现的称为工厂方法模式,有关更多详细信息,请参见如何在 C++ 中正确实现工厂方法模式。

于 2015-11-30T19:38:54.513 回答
2

虽然其他人正确地指出了如何对您想要编码的想法进行编码,但我将专注于另一件事。即,这里不恰当地使用了多态性。从无意义的 Object 继承所有东西闻起来像 Java,在 C++ 中是不受欢迎的。Princess 和 Monster 之间根本没有任何共同点(一个被亲吻,另一个被杀,怎么做取决于自己的口味),所以当两者都继承自 Object 时,很难编写出合适的游戏机械。您还必须存储实际的对象类型(例如,枚举),然后强制转换为这种类型 - 因为它们中只有一个对它们有方法kiss()

整个代码将是不安全演员的意大利面条,并且无法维护或推理。

相反,请采用强类型的方法。永远知道摆在你面前的是什么类型!

于 2015-11-30T19:49:08.620 回答
1

您应该动态处理数据。你现在所做的有几个问题。

更好的方法是:

CObject* CMap::insertObject(char character){ 
    if (character = '*') {
        return new CWall();
    }
...

这将利用多态性将实际类(例如CWall)隐藏在通用接口(CObject)后面。正如您所写,每个“新”对象,例如cdoor,实际上都会被传递给CObject. 这些都没有真正完成任何有意义的事情。

当然,您需要将这些创作与未来的适当破坏配对。

于 2015-11-30T19:42:45.123 回答
0

好吧,一方面,您实际上并没有初始化任何东西。CWall* cwall = new CWall;将是动态分配和初始化新的 CWall 对象(当然,假设 CWall 具有默认构造函数)或任何对象的正确方法。

您还需要记住的是,对于您分配的所有内容new,您必须delete稍后取消分配。因此,您需要考虑如何存储这些分配的对象,以便确保您的析构函数或清理函数在完成后删除所有这些对象。要考虑的一种设计模式是对象池,尽管很容易有几十种好方法来做到这一点。不过,这是您必须自己完成的步法,因为只有您对项目有足够的了解才能选择正确的设计模式。(我链接到的那本书是一个很好的资源。)

编辑:根据您的评论,还有另一个问题,那就是您要返回不同类型的对象。这是一个简单的继承问题——只要所有这些对象都继承自CObject(或类似的)抽象基类,您就可以简单地将返回类型列为CObject*. 然后,只要您返回一个继承自 的对象(或指向对象的指针)CObject,您就是黄金。

编辑 2:每当您使用new时,您实际上都会获得一个指向动态分配对象的指针。这会产生一些自身的问题,包括new如果分配失败可能会返回空指针。一定要检查一下!智能指针可以防止许多这些问题,但您对智能指针的使用取决于您的设计模式选择。

于 2015-11-30T19:39:18.480 回答