流氓喜欢游戏初始化错误

时间:2015-11-30 19:35:55

标签: c++ polymorphism instance dynamic-memory-allocation roguelike

我正在为简单的流氓式游戏制作一个简单的地图。 所以我需要通过从字符数组[i] [j]接收数据来初始化使用为每个数组单元创建的对象的映射。 建议这样的CWall,CDoor类在其他文件中定义,如CWall.cpp,CWall.h,Underneath是在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 个答案:

答案 0 :(得分:3)

这不是正确的做法。您受object slicing约束,因为我的猜测是您的CObject是一个对象,而不是指向某个对象的指针。您需要在函数中返回类型为CObject*的指针,然后针对每种情况返回new CMonsternew CPlayer等等。更好的是,使用智能指针代替。

您尝试实施的内容称为工厂方法模式,请参阅例如How to implement the factory method pattern in C++ correctly了解更多详情。

答案 1 :(得分:2)

虽然其他人正确地指出了如何编码您想要编码的想法,但我将专注于另一件事。即,这里多态性的使用不当。从无意义的对象继承一切就像Java一样,并且在C ++中不受欢迎。公主和怪物之间没有任何共同之处(一个是亲吻,另一个是被杀,并且做了最符合一个人品味的东西),所以当两者都是从Object继承时,它是非常难的编写适当的游戏机制。您还必须存储实际的对象类型(例如,枚举),而不是强制转换为此类型 - 因为只有其中一个将有方法kiss()

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

相反,选择强力打字的方式。始终知道你面前的类型!

答案 2 :(得分:1)

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

更好的方法是:

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

这将利用多态来隐藏通用接口(CWall)后面的实际类(例如CObject)。在您编写它时,每个“新”对象(例如cdoor)实际上将传递给CObject的复制构造函数。其中没有一个实际上完成了任何有意义的事情。

当然,你需要将这些创作与正确的破坏配对。

答案 3 :(得分:0)

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

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

编辑:根据你的评论,还有另外一个问题,那就是你要返回不同类型的对象。这是继承的简单问题 - 只要所有这些对象都从CObject(或类似的东西)的抽象基类继承,您只需将返回类型列为{{ 1}}。然后,只要你返回一个继承自CObject*的对象(或指向一个对象的指针),你就是金色的。

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