多个C ++文件和变量范围

时间:2011-04-18 13:51:05

标签: c++ scope

我有一个程序,它在winmain中启动,它在循环中调用run_game。

因为我将run_game视为主函数,所以我必须定义许多全局变量。

win main位于一个文件中,所有内容都在另一个.cpp文件中。它起初是一本书的教程,我现在已经加入了一段时间。因为我的代码变得如此之大,我想把它分成几个.cpp文件,但我有一些关于这样做的问题。

  1. 我看到很多人都有一个巨大的源文件。我是自学成才,所以不确定这是否有好处或只是风格。

  2. 人们说应该避免使用全局变量,这样我怎么能在其他文件中的函数中声明变量。

  3. 我的程序在函数中是不是很糟糕,因为我的计划是将run_game函数分解为几个较小的函数,每个函数都不是游戏的状态。

  4. 我知道人们可能会抱怨这是模糊的,所以如果你投票结束,请评论我如何能使问题更清楚。

    编辑:我确实知道如何使用类,并且在该程序的头文件中有4个类和3个结构,但是类的实例与变量的作用相同,因此不能解决范围问题。

5 个答案:

答案 0 :(得分:6)

  

我看到很多人都有一个巨人   源文件。我不是自学成才   确定这是有益还是只是   风格。

通常更好的是使用较小的明确定义的文件而不是一个巨大的源文件。每个文件都有一个C ++类定义或一组相互关联的函数。粗略的准则是不超过几百行的C ++代码,但它的主观性和难以量化。您可能经常需要更少或更多。

  

人们说应该避免使用全局变量   那么如何才能创建我声明的变量   在其他文件中可用的功能中。

您需要将这些变量作为参数传递给这些函数。例如,如果run_game调用foo,并且foo需要知道当前分数,则将分数作为参数传递,如下所示:

void run_game()
{
     int score = 0;

     ...
     foo(score);
}


void foo(int score)
{ 
    // do some stuff
}

这被称为“按值传递”,foo正在获得自己的分数副本。因此,如果foo更新得分,则调用者的副本将不会更新。您可以通过引用传递来让foo更新分数:

void foo(int& score) // notice the ampersand
{
    // add 100 pts
    score += 100;
}

现在你可能会问,我有50个变量,我怎么可能将所有50个变成foo?这是软件工程的艰苦工作发挥作用的地方。你有几个选择。在任何选项中,您都要考虑变量的组合方式。您可能会发现您总是将相同的5个变量传递给函数foo。也许它是游戏中迄今为止球员成就的一些表现。将这些组合在一起的最简单方法是使用struct:

struct PlayerAccomplishments
{
    int playersScore;
    int numGoblinsSlayed;
    int numTrollsSlaved;
};

现在您可以声明此类型的变量,设置特定字段并传递它们:

void run_game()
{
     PlayerAccomplishments accomplishments;

     ...
     foo(accomplishments);
}


void foo(PlayerAccomplishments& playerAccomps)
{ 
    // do some stuff
    playerAccomps.numTrollsSlayed++;
    playerAccomps.playerScore += 100;
}

抽象的下一步是将一组变量和常用功能包装到一个类中。这使我们可以轻松地共享通用功能,并强制实施一种安全,好的方式来操作这些对象 - 由该对象的成员函数定义。例如,如果我们有一个玩家类。

class Player
{
private:
    int score;
    int numTrollsSlayed;
public:
    // safely update the player's score after slaying a troll
    void SlayTroll(Troll& aTroll);
};

// in the cpp
Player::SlayTroll(Troll& aTroll)
{
    score += 100;
    numTrollsSlayed += 1;
}

然后上面的代码变成:

void run_game()
{
     Player aPlayer;

     ...
     foo(aPlayer);
}


void foo(Player& aPlayer)
{ 
    Troll someTroll;
    aPlayer.SlayTroll(someTroll); // updates aPlayer's score
}

我希望您能看到有很多方法可以考虑这些问题,并且不容易弄清楚如何分离问题。这个答案几乎没有触及表面。 我推荐一本好的软件工程课程或书籍。这个东西很难。具有数十年经验的真正聪明的人在组织和编写软件的最佳方式上挣扎。但考虑到这些东西很棒。努力寻找改进代码的方法是很好的,这样你就能够理解你今天,明天和六个月后想要做的事情。

答案 1 :(得分:0)

各自答案:

  1. 拥有巨大的源文件有更多的缺点。即使对其中一个模块进行小的更改,也可以编译完整的文件(增加编译时间)。代码变得不易维护。如果划分多个文件,可以根据不同的模块命名这些文件,并在遇到问题时进入。
  2. 如果您使用C ++,那么只需在static(或class)中将这些全局变量声明为namespace变量。将class放在头文件中并在.cpp文件中定义static
  3. 这个问题是主观的。您应该始终根据您的要求以及您现在和将来更容易找到的内容来决定。

答案 2 :(得分:0)

游戏设计和架构是一个复杂的主题,从你的问题中不清楚你究竟想要完成什么。首先,巨大文件中的所有内容在性能方面没有任何好处。只要它是可读,它就是不错的风格,但是你会发现大多数时候,项目在某些时候都会增长,所以你会想要在不同的文件中分离不同的逻辑。 / p>

其次,巨大功能中的所有内容在C ++中确实是糟糕的风格。函数和面向对象的编程(类,方法)可以帮助人们编写和维护代码,即使在最简单的例子中也必须使用这些功能。他们支付额外的开销并且总是值得的。

第三个也是最后一个,全局是有争议的。有人说他们总是很糟糕。我会说这取决于。您没有在问题中提供足够的信息,以便我可以决定。但是,如果您有疑问,请仔细检查是否无法使用以更好的方式组织事物。对象可以具有状态(数据字段),其行为就像它们对于类中的方法是全局的一样,但是对于世界其他地方是隐藏的。阅读书籍或在互联网上搜索面向对象的编程。

答案 3 :(得分:0)

  1. 只有一个文件意味着每次更改内容时都会重新编译所有代码。根据您的机器和您拥有的代码量,它可能会很长。当然,随着代码库的增长(协作,组织代码......),您将遇到其他缺点。

  2. 和3.从你的意思来看,你似乎更像C语言而不是C ++。你知道什么是课程,对象......?它可以帮助你以较小的方式打破你的程序,但如果你使用功能方法,这可能意味着很多工作。

答案 4 :(得分:0)

  

编辑:我知道如何使用类和   有4个班级和3个结构   这个程序的头文件,但是   类的实例与a的作用相同   变量因此无法解决问题   范围。

这不是真的。这里的大多数帖子指向正确的方向。但是我错过了一个信息,即让一个班级来处理游戏状态是一个明智的决定 这个类将实例化类“游戏”并运行主循环。这个类还处理游戏时间和分数等变量。在这种方法中,您不需要全局变量,并且变量位于具有有限范围的类中。如果您熟悉类,那么您应该已经考虑过如何在类之间传递这些值 有很多关于游戏架构的资源。一种常见的方法是使用游戏循环和两种方法:移动和渲染,一种用于处理游戏,如移动角色,怪物和世界物品,另一种用于在屏幕上渲染游戏。

相关问题