调用Object超出范围C ++

时间:2014-01-28 02:17:33

标签: c++ object scope

我正在制作一个简单的基于文本的胭脂游戏。在我的代码中,我为“房间”创建了一个类,我在主文件中创建了一个名为“Dungeon”的房间实例。该对象范围产生了问题。我在'initGame()'函数中创建了它,但后来我无法在主游戏循环中访问它。

我将发布所有相关代码,谢谢!

room.h

#include <string>
#include "ConsoleCommands.h"
using std::string;


class room
{
public:
    room(void);
    room(string name);
    ~room(void);

        //This creates the cells and populates the map//
    static const int cellsX = 15;
    static const int cellsY = 10;

    string NAME;
    int map;

    void writeMap();
};

的main.cpp

int main(void)
{
    initGame();
    cout << "WELCOME, " + Player.NAME + " ";
    return 0;
};

void initGame(void)
{
    initCells();
    lifeForm Player(100, 100, 100, newGameMenu());
    room Dungeon("Dungeon");
}

4 个答案:

答案 0 :(得分:2)

当initGame返回时,Dungeon和Player会被破坏。从函数中返回房间和/或播放器实例。

您可以使用游戏结构:

struct Game
{
    Game() : Player(100, 100, 100, newGameMenu()), Dungeon("Dungeon")
    {
    }

    lifeForm Player;
    room Dungeon;
}

然后

int main(void)
{
    Game g;
    cout << "WELCOME, " + g.Player.NAME + " ";
    return 0;
};

答案 1 :(得分:0)

正如您所说,问题在于范围。对象

lifeForm Player(100, 100, 100, newGameMenu());
room Dungeon("Dungeon");

仅存在于

范围内
void initGame(void)

要解决这个问题,你可以尝试一些事情

1)在main中初始化对象。只需将声明从initGame()移到main即可。这不是非常模块化的,您希望在名为init的函数中使用初始化代码。

2)在init函数中创建初始化代码,并将对象返回到main。让initRoom()和initLifeForm()像以前一样创建,然后分别返回类型为room和lifeForm的对象。然后在主要副本中通过初始化程序或使用=。

int main(void)
{
   room theRoom = initRoom();
   lifeForm theLifeForm = initLifeForm();
}

这并不比1)好多了,甚至可能更糟,但至少你已经删除了初始化函数的特定初始化。当然,在这种情况下,为什么没有为此目的使用特殊的无参数初始化构造函数?

3)有一个游戏对象。这可能就是你想要的。这里room和lifeForm成为Game的成员,而initGame是Game构造函数。

答案 2 :(得分:0)

您的initGame函数会创建一些本地对象

void initGame(void)
{
    initCells();
    lifeForm Player(100, 100, 100, newGameMenu());
    room Dungeon("Dungeon");
}

让我们快速浏览一下这些陈述:

room Dungeon("Dungeon");

这是一个变量声明,但C ++使用作用域,这意味着上下文很重要。这里的范围是一个函数,所以你正在做的是声明一个“房间”的实例,被称为“Dungeon”,并通过调用room::room(std::string)来构建。

在C ++中,本地对象在堆栈中声明 - 这意味着当您离开作用域时程序展开堆栈,这些对象将被强制消失。

所以,如果你是C-ify上面的陈述,这大致是你会产生的代码:

void initGame(void)
{
    initCells();

    lifeForm* Player = alloca(sizeof(Player));
    Player->lifeForm(100, 100, 100, newGameMenu());

    room* Dungeon = alloca(sizeof(Dungeon));
    std::string dungeonName = std::string("Dungeon");
    Dungeon->room(dungeonName);

    // scope ends
    // destruct Dungeon
    Dungeon->~room();

    // destruct Player
    player->~lifeForm();

    // the stack space is automatically "released" by
    // leaving the function
}

这里的结果是物体完全消失了。如果你希望它们持久存在,你需要通过返回它们,在main中声明它们并通过引用它们来传递它们,或者将它们封装在它们自己的对象中来管理它们的生命周期。

答案 3 :(得分:-1)

如果您经常使用这些变量,可以将它们创建为任何函数之外的全局变量:

lifeForm g_Player;
room g_Dungeon;

int main(void)
{
    initGame();
    cout << "WELCOME, " + Player.NAME + " ";
    return 0;
};

void initGame(void)
{
    initCells();
    g_Player = Player(100, 100, 100, newGameMenu());
    g_Dungeon = Dungeon("Dungeon");
}

然后,只要您在初始游戏后需要访问这些对象,就可以使用全局对象

void Death(void)
{
    g_Player.Lives--;
}