【问题标题】:Header guards in multiple files, and they are all dependant on eachother and I have more than 2 HPP files which need eachother多个文件中的标头保护,它们都相互依赖,我有超过 2 个需要相互依赖的 HPP 文件
【发布时间】:2014-03-22 16:07:58
【问题描述】:

我在谷歌上搜索了近 4 天,每天几个小时,没有结果。我不想让它走到这一步,但我真的找不到任何东西。 现在,我将描述我的问题 - 询问您是否需要澄清:

问题:我有 3 个相互循环依赖的 HPP 文件, 除了避免“#include 嵌套太深”的问题外,标头守卫根本没有帮助。但现在我收到以下错误:'forest' is not declared in this scope

#ifndef MAINMENU_HPP
#define MAINMENU_HPP
#include <iostream>
#include <windows.h>
#include <fstream>
#include <string>
#include <stdlib.h>
#include <time.h>
using namespace std;

#ifndef MAINMENU_HPP
#include "Areas.hpp"
Areas areas;
#endif
#include "Player.hpp"

#include "SetColor.hpp"
void mainMenu();


void mainMenu()
{
    int action;
    //battle();
    initPlayer();
    if(player.xp >= player.xpRequired)
        {
            player.xp -= player.xpRequired;
            player.lvl += 1;
            SetColor(14);
            cout << endl << "_-*You have leveled up!*-_" << endl << endl;
            SetColor(7);
            player.xpRequired = 40 + player.lvl * 10 * player.lvl;
            levelUp();
        }
    player.damageModifier = 5 + player.strength/2;
    player.baseDamage = 5 + player.strength/2;

    cout << "=================================City of Town==================================" << endl;
    cout << "Made by Erik aka Einar aka NukeTester and Mr.WertyQaz" << endl;
    cout << "Enter [0] to quit" << endl;
    cout << "Enter [1] to view stats" << endl;
    cout << "Enter [2] to go to the forest" << endl;
    cout << "Enter [3] to save the game" << endl;
    cin >> action;

    switch (action)
        {
        case 0:
            //quit();
            break;
        case 1:
        player.xp = 400;
        cout << player.playerName << "'s Inventory " << endl;
        cout << "Health: ";
        SetColor(13);
        cout << player.health;
        SetColor(7);
        cout << "/";
        SetColor(13);
        cout << player.maxHealth << endl;
        SetColor(7);
        cout << "Gold: ";
        SetColor(14);
        cout << player.money;
        SetColor(7);
        cout << endl;
        cout << "Experience: ";
        SetColor(3);
        cout << player.xp;
        SetColor(7);
        cout << "/" ;
        SetColor(3);
        cout << player.xpRequired << endl;
        SetColor(7);
        cout << "Level: ";
        SetColor(2);
        cout << player.lvl << endl;
        SetColor(7);
        cout << "Strength: " << player.strength << endl;
        cout << "Dexterity: " << player.dexterity << endl;
        cout << "Vitality: " << player.vitality << endl;
        cout << "Speed: " << player.speed << endl;
        system("PAUSE");
        system("CLS");
        mainMenu();
        break;
        case 2:
        forest(); // THIS IS THE ERROR
        break;
        }
        }
#endif

//Areas.hpp (Where forest lays)
#ifndef MAINMENU_HPP
#include "MainMenu.hpp"
MainMenu menu;
#endif

#ifndef AREAS_HPP
#define AREAS_HPP

#include <iostream>
#include <windows.h>
#include <fstream>
#include <string>
#include <stdlib.h>
#include <time.h>

#include "SetColor.hpp"

using namespace std;


void battle();
void forest();


void battle()
{
    int action;
    system("CLS");
    srand (time(NULL));
  /* generate secret number between 1 and 10: */
    int monster;
    monster = rand() % 2 + 1;

    goblin.enemyID = monster;
    if(goblin.enemyID == 1)
{
    goblin.enemyName = "Goblin";
    goblin.dead = false;
    goblin.enemyID = 1;
    goblin.health = 33;
    goblin.baseDamage = 3;
    goblin.damageModifier = 5;

    srand (time(NULL));
    goblin.damage = rand() % goblin.damageModifier + goblin.baseDamage;

    srand (time(NULL));
    goblin.money = rand() % 5 + 10;
    cout << "====================================BATTLE======================================";
    cout << "Opponent: " << goblin.enemyName << endl;
    cout << "It's health is: " << goblin.health << endl;
    cout << "Do you want to battle it?" << endl;
    cout << "Enter [1] for yes" << endl << "Enter [2] for no" << endl;

    cin >> action;
        if(action == 1)
        {
            BattleGoblin:
                    if(player.health <=0)
        {
            player.dead = true;
        }
    if(player.dead){
            cout << "You have died! Game Over!" << endl;
            cout << "Press Enter to continue..." << endl;
            system("PAUSE");
            //quit();
    }
            cout << "Enter [3] for a quick heal" << endl;
            cin >> action;
            if(action == 3)
                {
                    player.health = player.maxHealth;
                    goto BattleGoblin;
                }
    if(action == 1)
        {
            //Player Damage

            player.damage = rand() % player.damageModifier + player.baseDamage;
            goblin.health -= player.damage;

            cout << "You deal ";
            SetColor(4);
            cout << player.damage;
            SetColor(7);
            cout << " damage to the evil Goblin!" << endl;
            cout << "Goblin health: " << goblin.health << endl;

            //Goblin Damage
            if(goblin.health >0)
                {
            srand (time(NULL));
            goblin.damage = rand() % goblin.damageModifier + goblin.baseDamage;

            cout << "Goblin strikes you, dealing " << goblin.damage << " damage!" << endl;
            player.health -= goblin.damage;
            cout << "Your health: ";
            SetColor(13);
            cout << player.health << endl;
            SetColor(7);
            system("PAUSE");
            system("CLS");
            }
            else if(goblin.health <=0)
        {
            SetColor(2);
            cout << "Goblin is now DEAD!" << endl;
            SetColor(7);
            system("PAUSE");
            system("CLS");
            goblin.dead = true;
        }
      if(goblin.dead)
        {
            cout << "You killed the greedy Goblin!" << endl;
            cout << "You have earned " << goblin.money << " Gold Coins!" << endl;
            cout << "You have also gained a total 5 experience from the Goblin!" << endl;
            player.money += goblin.money;
            player.xp += 5;
            system("PAUSE");
            menu.mainMenu();
        }
            goto BattleGoblin;
            }
        }
        if(action == 2)
        {
            srand(time(NULL));
            int fleeOpponent = rand () % 4 + 1;

        if(fleeOpponent >=2)
        {
            cout << "You flee the evil Goblin. " << endl;
            system("PAUSE");
            system("CLS");
            mainMenu();
        }
        else if (fleeOpponent == 1)
        {
            cout << "The evil Goblin catches you, before you get away, and deals 5 damage!" << endl;
            player.health -= goblin.damage;
            goto BattleGoblin;
        }

            cout << "You flee the evil Goblin. " << endl;
            system("PAUSE");
            system("CLS");
            mainMenu();
        }
        if(action > 2)
            {
                cout << "Undefined action. Press Enter.";
                cin.get();
                goto BattleGoblin;
            }
}


//=========================================================================================================================================================================================


    orc.enemyID = monster;
    if(orc.enemyID == 2)
    {
    orc.enemyName = "Orc";
    orc.dead = false;
    orc.enemyID = 1;
    orc.health = 140;
    orc.baseDamage = 7;
    orc.damageModifier = 8;

    srand(time(NULL));
    orc.damage = rand() % orc.damageModifier + orc.baseDamage;

    srand (time(NULL));
    orc.money = rand() % 7 + 3;
    cout << "====================================BATTLE======================================";
    cout << "Opponent: " << orc.enemyName << endl;
    cout << "It's health is: " << orc.health << endl;
    cout << "Do you want to battle it?" << endl;
    cout << "Enter [1] for yes" << endl << "Enter [2] for no" << endl;
    cin >> action;
    if(action == 1)
        {
            BattleOrc:
                    if(player.health <=0)
        {
            player.dead = true;
        }
    if(player.dead){
            cout << "You have died! Game Over!" << endl;
            cout << "Press Enter to continue..." << endl;
            cin.get();
            //quit();
    }
            cout << "Enter [1] for attack" << endl;
            cout << "Enter [3] for a quick heal" << endl;
            cin >> action;
            if(action == 3)
                {
                    player.health = player.maxHealth;
                    goto BattleOrc;
                }
    if(action == 1)
        {
            player.damage = rand() % player.damageModifier + player.baseDamage;
            orc.health -= player.damage;

            cout << "You deal ";
            SetColor(4);
            cout << player.damage;
            SetColor(7);
            cout << " damage to the evil Orc!" << endl;
            cout << "Orc health: " << orc.health << endl;

            srand(time(NULL));
            orc.damage = rand() % orc.damageModifier + orc.baseDamage;
            if(orc.health >0)
                {
            cout << "Orc strikes you, dealing " << orc.damage << " damage!" << endl;
            player.health -= orc.damage;
            cout << "Your health: " << player.health << endl;
            system("PAUSE");
            system("CLS");
                }
                else if(orc.health <=0)
        {
            SetColor(2);
            cout << "Orc is now dead!" << endl;
            SetColor(7);
            system("PAUSE");
            system("CLS");
            orc.dead = true;
        }
      if(orc.dead)
        {
            cout << "You killed the ferocius Orc!" << endl;
            cout << "You have earned " << orc.money << " Gold Coins!" << endl;
            cout << "You have also gained a total 21 experience from the Orc!" << endl;
            player.money += orc.money;
            player.xp += 21;
            system("PAUSE");
            mainMenu();
        }
            goto BattleOrc;
            }
        }
     if(action == 2)
        {
            srand(time(NULL));
            int fleeOpponent = rand () % 4 + 1;

        if(fleeOpponent >=2)
        {
            cout << "You flee the evil Orc. " << endl;
            system("PAUSE");
            system("CLS");
            mainMenu();
        }
        else if (fleeOpponent == 1)
        {
            cout << "The evil Orc catches you, before you get away, and deals 5 damage!" << endl;
            player.health -= orc.damage;
            goto BattleOrc;
        }

            cout << "You flee the evil Orc. " << endl;
            system("PAUSE");
            system("CLS");
            mainMenu();
        }
        if(action > 3)
            {
                cout << "Undefined action. Press Enter.";
                cin.get();
                goto BattleOrc;
            }
}
}



void forest()
{

    int action;
    system("CLS");
    cout << "===================================FOREST=======================================";
    cout << "Enter [0] to go back to town" << endl,
    cout << "Enter [1] to chop some wood" << endl;
    cout << "Enter [2] to go for a walk. Might be risky..." << endl;

    cin >> action;
    if(action == 0)
        {
//            mainMenu();
        }
    if(action == 1 && player.hasHatchet)
        {
            cout << "you cut some wood.";
            system("PAUSE");
            system("CLS");
//            mainMenu();
        }

        else if(action == 1)
            {
                cout << "You can't chop trees without a hatchet! Go buy one at the blacksmith!" << endl;
                system("PAUSE");
                system("CLS");
//                mainMenu();
            }
    if(action == 2)
        {
            srand (time(NULL));
            int forestBattle;
            forestBattle = rand() % 10 + 1;
            if(forestBattle >=1 && forestBattle <=5)
                {
                    cout << "You walk into the forest." << endl << "All you found was peace. You decide to head back to town." << endl << endl;
                    system("PAUSE");
                    system("CLS");
//                    mainMenu();
                }
                if(forestBattle >=5 && forestBattle <10)
                    {
                        cout << "Something is heading towards you!" << endl;
                        system("PAUSE");
                        system("CLS");
                        //battle();

                    }
            if(forestBattle == 10)
                {
                    cout << "You found some fresh apples laying on the ground. You eat the apples and gain +1 health." << endl << endl;
                player.health += 1;
                system("PAUSE");
                system("CLS");
//                mainMenu();
                }
        }
}

#endif

//main.cpp
#ifndef MAINMENU_HPP
#include "MainMenu.hpp"

#endif
//#endif // MAINMENU_HPP
#include <iostream>
#include <windows.h>
#include <fstream>
#include <string>
#include <stdlib.h>
#include <time.h>
#include "Player.hpp"
#include "MainMenu.hpp"

using namespace std;

int action = 0;


int quit();
void matchMaking();
void battle();
void saveGame();
void setColor();

int quit()
{
    exit(1);
}

void matchMaking()
{

}


void saveGame()
{
    std::string saveName = "save";

    cout << "Enter savegame name: ";
    std::getline(std::cin, saveName);
    ofstream save(saveName.c_str());
    save << "Health: " << player.health << endl << "Damage: " << player.damage << endl << "Gold: "  << player.money << endl << endl;
}


int main()
{
//Initialize functions
    initPlayer();
    mainMenu();

//Initialize local variables
/*
v1 = rand() % 100;         // v1 in the range 0 to 99
v2 = rand() % 100 + 1;     // v2 in the range 1 to 100
v3 = rand() % 30 + 1985;   // v3 in the range 1985-2014
*/
}

//Strangest thing of all, because this is included in different files more than twice, but
//this works fine! I don't have any idea why.
#ifndef SETCOLOR_HPP
#define SETCOLOR_HPP

#include <iostream>
#include <windows.h>
#include <fstream>
#include <string>
#include <stdlib.h>
#include <time.h>

//#include "Player.hpp"

using namespace std;

void SetColor(int value);

void SetColor(int value)
{
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),  value);
}
#endif

如您所见,我几乎绝望地发布了我的整个项目,只是为了寻求帮助! 这意味着我现在对 C++ 非常生气。 如您所见,我是一个新手程序员,但我认为这对我来说是中等难度 制作一个简单的 RPG 游戏,使用单独的 HPP 文件,而不是像以前那样将所有代码放在 main.cpp 中。

先谢谢了,我希望这不会太麻烦,至少对于专业程序员来说不是!

也许这有助于澄清: 我使用了一个名为 PenguinProgrammer 的网站:http://www.penguinprogrammer.co.uk/rpg-tutorial-2/battles/

你可以看到这家伙使用了“battle.hpp”,还做了这样的事情:

#include "dialogue.hpp"
Dialogue dialogue;

而且我不明白这似乎对他有用,而不是对我有用。 我没有测试过他的代码,我也不是一个好的程序员,但在我的世界里,这似乎 真的很奇怪! 有答案吗?

【问题讨论】:

  • 头文件中真的有变量和函数定义吗?
  • 我不这么认为,你可以检查代码,因为我不确定如何正确声明函数定义和变量

标签: c++ file include


【解决方案1】:

您要做的是创建一个循环引用,这在 C++ 中是不允许的。

头文件应该出现在每个头文件中,而不是你的源文件中,例如:

#ifndef HEADER_NAME_MACRO
#define HEADER_NAME_MACRO

//Header contents...

#endif

要解决循环引用问题,您需要重新审视您的设计以消除循环引用。通常,您会通过让一个或多个标头仅通过指针或引用引用其他内容并转发声明其他类来做到这一点:

标题 A:

#ifndef HEADER_A
#define HEADER_A
//Forward declaration, you've told the compiler you'll eventually define B.
class B;

class A {
public:
    B* b;
};

#endif

和标题 B:

#ifndef HEADER_B
#define HEADER_B

#include <A.hpp>

class B {
public:
    A a;
};

这样做的原因是 C++ 编译器需要在定义时知道您定义的所有内容的大小。如果你有一个循环引用,编译器不知道你定义的第二个的大小。

您还将在链接时遇到头文件中定义的非成员函数的问题。要解决此问题,您需要将它们放入源文件或声明它们inline 以绕过one definition rule

您似乎误解了人们通常如何用 C++ 组织代码。标头应包含声明,您的源文件应包含定义。见this c++-faq question about the difference

【讨论】:

  • 感谢您的详细解释!我将重写我的代码,看看会发生什么!谢谢!
【解决方案2】:

您不需要在任何 .cpp 文件中添加包含保护,您应该只在头文件中使用包含保护。我可以看到您在 main.cpp 文件的许多地方添加了包含保护。

Inclusion guard 应该在你的头文件的第一行添加,即使头文件被多次包含,你也只会得到一次它的内容,因为其余部分会在 prepossessing 后被删除。

【讨论】:

  • 感谢您的回答!我会检查一下是否有帮助!
  • 我应该在哪里添加标题防护/我应该如何添加标题防护?我见过这样守卫的人:#ifndef FOO_H #define FOO_H int x;整数y; #endif 还有类似的:#ifndef FOO_H #define FOO_H #include "Bar.h" #endif class Foo { //BLA BLAH BLAH };
  • 标题 #ifndef HEADER_A #define HEADER_A 的开始和标题的结束 #endif。就是这样。只需给出正确的名称,如果文件名是 CircleClass.h 则 #ifndef CIRCLE_CLASS
  • 感谢您的澄清!我想我将不得不重新编写我的游戏引擎,以使其正常工作,没有像我遇到的那些错误。
  • @Einar 在决定做大量艰苦的工作之前,请正确理解问题。可能问题很小,你最终会做很多工作。有时调试问题需要比预期更多的时间。
【解决方案3】:

它找不到forest(),因为您在Areas.hpp 之前使用了一个已经定义的包含保护

#ifndef MAINMENU_HPP
#define MAINMENU_HPP

// ...

#ifndef MAINMENU_HPP
#include "Areas.hpp"
Areas areas;
#endif

// ...

要解决循环依赖,通常需要在头文件中使用前向声明。

在您的情况下,将函数 definitions 移动到 .cpp 文件中并在头文件中仅保留 声明 就足够了。

【讨论】:

  • 感谢您的帮助!我会看看我能不能做到这一点,然后解决这个地狱般的问题!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-02
  • 2011-04-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多