如何让非全局对象在函数内进行交互?

时间:2010-09-11 17:08:48

标签: c++ oop object

我正在尝试使用C ++创建一个Breakout克隆,因此有几个对象(如ball,paddle,powerupicon,block等)。我知道将它们放在全局范围内是不好的做法,所以它们在main()中初始化。问题在于需要从其他函数(如redraw()或reset_game())中对这些对象进行处理。我能想到的唯一方法就是将对象的引用传递给每个函数,但我不确定这是否是最好的方法。

基本上,从函数中处理这些对象的最佳方法是什么?通过参考传递它们?使它们全局但在命名空间内?还是完全不同的东西?

6 个答案:

答案 0 :(得分:2)

一种简单的(不一定是灵活的或强大的)方法是定义一个基类game_object类,用于定义与游戏对象的接口,并存储它们。你的对象继承它。:

class game_object
{
public:
    virtual ~game_object() {}

    virtual void update() = 0;
    virtual void draw() = 0;

    // get and set position
    virtual vector3 position() = 0;
    virtual void position(const vector3&) = 0;

    // etc...
};

class ball : public game_object
{
public:
    void update() { /* update the ball */ }
    void draw() { /* draw the ball */ }

    // etc
};

// etc

现在您有一种使用游戏对象的常用方法。接下来,您可以将它们存储在地图中(如果您有Boost,TR1或C ++ 0x),最好将其存储在unordered_map中,并使该地图全局可用:

// game_object_manager.h
typedef std::map<std::string, game_object*> game_object_manager;

extern game_object_manager manager;

您可以在某处翻译单元(main.cppgame_object_manager.cpp)中对此进行定义。最后,您可以通过按名称插入内容来使用它:

// somewhere, add the ball
manager.insert(std::make_pair("ball", new ball()));

并使用它:

game_object* b = manager["ball"];
if (!b) /* there is no ball object */

// use b as ball */

同样,这是一个简单的解决方案,不一定是健壮的,最佳实践或灵活的。但对于第一场比赛,它会很好。 (为了改进它,你想要研究异常安全,智能指针和其他东西(游戏书籍)。我建议你在尝试制作游戏之前这样做。)

答案 1 :(得分:1)

引自cppreference

static 关键字可以通过四种不同的方式使用:

  • 为函数中的局部变量创建永久存储,
  • 创建一个类数据副本,
  • 声明与非成员函数相似的成员函数,以及
  • 指定内部链接。

还有其他例子。

void foo()
{
    static int counter = 0;
    cout << "foo has been called " << ++counter << " times\n";
}

int main() 
{
    for( int i = 0; i < 10; ++i )
        foo();
}

答案 2 :(得分:0)

如果它正在初始化您担心的顺序,您可以在全局范围内指向它们,可能在命名空间中,并在main中为它们分配内存。

答案 3 :(得分:0)

游戏编程模式中Singletons的章节可以帮助您,特别是"What We Can Do Instead"部分。

答案 4 :(得分:-1)

我会创建一个包含所有这些信息的管理器对象。就像有Game成员paddlebricksitems等的成绩Game一样。然后你可以让currentGame有一个类方法class Game { public: Paddle *paddle; vector<Brick> *bricks; vector<Item> *items; static Game *currentGame(); static void setCurrentGame(Game *newGame); private: static Game *currentGameInstance; } static Game *Game::currentGame() { return currentGameInstance; } static void Game::setCurrentGame(Game *newGame) { currentGameInstance = newGame; } 返回当前游戏实例。这有点像在“全球范围”,但更多的OOP方式。

E.g:

Game::currentGame()->paddle

(我对C ++非常生疏,希望语法正确)

这样你可以随心所欲地{{1}}。

答案 5 :(得分:-1)

“最好”有点主观;您已经命名了标准方法(即:命名空间中的全局或有效等效,或传递给每个函数)。

我倾向于在设计方面做的是通过逻辑分组将组对象放在一起(例如:“游戏状态”对象中的某些内容,“UI资源”对象内的其他内容等),然后生效这些对象的全局实例。我建议总是为对象提供一个有效的命名空间:这可以是字面意思,或者像单例或命名实例工厂范例。通常,对象越“本地”,我越倾向于将它们明确地传递给使用/操纵它们的函数;对象越“应用程序级别”,我就越倾向于使它们成为有效的全局变量。

希望有所帮助。