SFML C++:我的软件中发生的神秘错误可能与 <iostream> 和 header 文件有关?

SFML C++: mysterious bugs happening in my software possibly relating to <iostream> and header files?

我正在制作一个项目,为了使它井井有条,我制作了一个名为 include.h 的 header 文件,它将存储所有全局变量并包含在内。 昨天它成功了,但今天它给我带来了一些奇怪的错误,我找不到解决它们的方法。

#include <SFML/Graphics.hpp>
#include <iostream>
#include <stdio.h>

enum GameModes { AgainstComputer, AgainstPlayer, AgainstPc, GameModeScreen }; <- error: C2011: enum 
                                                                                 type redefinition
/*
    enum explanation:
        0 = play against AI
        1 = play online against player
        2 = play locally against a friend
        3 = open the screen showing game modes
*/

// font name
std::string fontName = "Arvo-BoldItalic.ttf"; <- error: C2374: redefinition; multiple initialization

这是包含 header 的代码,其中有 2 个错误表明我对变量进行了两次初始化,尽管我没有这样做。

其他相关的错误在正常功能中:

GameModes welcomeWindow(sf::RenderWindow &window, sf::Event event)
{
    sf::Font font;

    if (!font.loadFromFile("C:\chess\Fonts\" + fontName)) <- error: C2088: illegal for class 
                                                                (where is there a class involved?)
    {
        std::cout << "Error loading font " << fontName << std::endl; <- error: C2088: illegal for 
                                                                        class (where is there a class 
                                                                        involved?)
        exit(1);
    }

我基本上是在尝试从以 includes.h header 中的文件名命名的文件中加载字体,但它会出现两个错误:(在代码行中说明)

我认为重新定义的发生是因为缺少 header 守卫!

也许今天您将 header 包含在两个文件中,所以现在该代码得到 运行 两次,因此所有符号都被重新定义。

您还可以在所有 header 文件的开头使用 #pragma once 来告诉您的 link 用户只包含该文件一次。

嗯,我对在 headers 中声明的全局变量没有太多经验,但我想我曾经有过这样一个奇怪的错误,我不得不在所有顶部转发声明全局变量它与

一起使用的 cpp 文件
extern fontName;

Wiki post 关于 header 守卫:

https://en.wikipedia.org/wiki/Include_guard

添加到我的答案中。所有以 # 开头的行实际上都是预处理器指令,这意味着它们的更改甚至发生在您的代码编译之前。

您可以想象,当您的代码包含一个包含项时,所有 header 实际上都会与包含项一起粘贴到该文件中!

此外,#ifndef NAME 的意思是,只有当预编译器不知道符号 NAME 时,该控制结构的 body 才会 运行。

如果是,那么#ifndef 和 #endif 之间的所有内容都将被忽略。

注意我们做的第一件事是 #define NAME,从而让预处理器知道该符号存在,但为此我们甚至不需要定义 [=14= 的值], 因为它不相关。

这样,下次预处理器找到 #include "thatFile.h" 时,它实际上不会复制任何代码。

这种控制结构还有很多。例如,可以使用 #ifdef __unix__ 包含仅存在于 Linux 中的 header,这样在不同的 OS 中编译时不会导致错误,并允许更大的可移植性!

编辑:将 link 更改为桌面和英语 edit2:我的解释是错误的