C++ 共享全局变量而不使用extern的最佳方法?

C++ 共享全局变量而不使用extern的最佳方法?,c++,global,C++,Global,所以我想要的是有一个全局的.h文件,其中包含其他类/函数使用的变量/函数。例如,假设我有三个头文件:global.h、local1.h和local2.h。这里,local1.h和local2.h将使用global.h中的变量。但是,如果在local1.h和local2.h中都包含global.h,则会像预期的那样导致多定义错误。我知道我们可以使用关键字“extern”,但我听说这是一种不好的做法,所以我试图避免这种情况 我试图通过使用类来解决这个问题。基本上,我有一个基类,它包含所有静态变量。这

所以我想要的是有一个全局的.h文件,其中包含其他类/函数使用的变量/函数。例如,假设我有三个头文件:global.h、local1.h和local2.h。这里,local1.h和local2.h将使用global.h中的变量。但是,如果在local1.h和local2.h中都包含global.h,则会像预期的那样导致多定义错误。我知道我们可以使用关键字“extern”,但我听说这是一种不好的做法,所以我试图避免这种情况

我试图通过使用类来解决这个问题。基本上,我有一个基类,它包含所有静态变量。这样,任何使用这些变量的类都可以从基类继承。(就我而言,我对它没意见,因为我的大部分程序都是在课堂上完成的)。下面是代码

Base.h

class base{
    static const int SCREEN_SIZE = 1000;
};
类别1.h

#include "base.h"
class class1: public base{
    void printSize(){
        cout << SCREEN_SIZE << endl;
    }
};
但我不确定这是不是最好的方法,有什么建议吗

这是我的实际代码:

#ifndef GAME_CORE_H
#define GAME_CORE_H

#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <SDL2/SDL_ttf.h>
#include <stdio.h>

namespace Colors{
const SDL_Color RED = {255, 0, 0, 255};
const SDL_Color GREEN = {0, 255, 0, 255};
const SDL_Color BLUE = {0, 0, 255, 255};
const SDL_Color YELLOW = {255, 255, 0, 255};
const SDL_Color PURPLE = {128, 0, 128, 0};
const SDL_Color ORANGE = {255, 68, 0, 255};
const SDL_Color WHITE = {255, 255, 255, 255};
const SDL_Color BLACK = {0, 0, 0, 255};
};

namespace GAME_CORE{
SDL_Window* gWindow = NULL;
SDL_Renderer* gRenderer = NULL;
SDL_Surface* gWindowSurface = NULL;
TTF_Font* defaultFont = NULL;

const int SCREEN_INIT_WIDTH = 1280;
const int SCREEN_INIT_HEIGHT = 720;
const int TILESIZE = 32;

void CORE_Init();
};


#endif // GAME_CORE_H
#ifndef游戏(核心)
#定义游戏核心
#包括
#包括
#包括
#包括
名称空间颜色{
const SDL_Color RED={255,0,0,255};
const SDL_Color GREEN={0,255,0,255};
const SDL_Color BLUE={0,0,255,255};
const SDL_Color YELLOW={255,255,0,255};
const SDL_Color PURPLE={128,0,128,0};
const SDL_Color ORANGE={255,68,0,255};
const SDL_Color WHITE={255,255,255};
const SDL_Color BLACK={0,0,0,255};
};
名称空间博弈核心{
SDL_窗口*gWindow=NULL;
SDL_渲染器*gRenderer=NULL;
SDL_曲面*gWindowSurface=NULL;
TTF_Font*defaultFont=NULL;
const int SCREEN_INIT_WIDTH=1280;
屏幕初始高度=720;
常数int TILESIZE=32;
void CORE_Init();
};
#endif//游戏_核心_H
因此,错误msg显示了
gWindow、grender、gWidowSurface和defaultFont

我建议.h文件应该用于原型,而不是实际声明任何类型或函数,除了:

内联变量/函数 静态变量/函数 常量变量 使用int=Reg;typedef Reg int

我希望您通过两种方式实现它

var.h
class var{
   public:
    var()=default;

  private:
     int _list {};

    operator +(int); //prototypes

};



var.cpp
//Then u can implement the declaration like
   #include"var.h"
    class var{
    //Implement it here

   };
或者,您可以像标准库那样在没有扩展名的文件中声明完整类

这是一个C程序,可以生成这些文件

int main (void){
   FILE* ptr = fopen ("vector","w+");
}
使用收割台护罩

比如说

Base.h

#ifndef base_h
#define base_h
class base{
    static const int SCREEN_SIZE = 1000;
};
#endif

首先,如果您多次包含一个标题,那么如果您允许通过多次包含重复代码,那么您总是会得到多个定义。使用
extern
关键字来解决问题不是一个好办法,您可以将其用于其他目的。除此之外,它在课堂上不起作用

正确的方法是在头文件中使用include-guard:

#ifndef SOME_GUARD_NAME
#define SOME_GUARD_NAME
// your code in between here
#endif
如果您遇到过一次
#pragma
:这起作用是相同的,但不是标准的。我不知道最近有哪个编译器不支持它,但是如果你想保持完全的可移植性,还是添加include-guard作为后备

extern
关键字用于告诉编译器变量存在,但在别处定义。如果从不同的编译单元访问全局变量,则需要在其中一个中定义全局变量,而其他变量则通过声明(使用
extern
关键字)知道

将常量定义为全局变量(delcareed
extern
)并没有太大问题:

它们是常量,因此避免了全局变量带来的麻烦,因为它们无论如何都不可修改(即使在多线程环境中并发读取也不是问题)

但是,很容易就无法了解修改可变全局变量的位置和时间(这是全局变量的错误做法,而不是
extern
关键字…)。在多线程环境中,您可以添加一个重要因素。错误很容易从中产生。这就是为什么您通常避免使用全局变量

仔细查看您的名称空间
GAME\u CORE
,然后将其转换为类似乎是个不错的主意:

class GameCore
{
    // depends on how they are created, maybe std::unique_ptr is more appropriate?
    // you might avoid necessity of a destructor
    SDL_Window* m_window;
    SDL_Renderer* m_renderer;
    SDL_Surface* m_windowSurface;
    TTF_Font* m_defaultFont; // maybe rather a static constant?

public:
    // constants can easily be public:
    unsigned int const SCREEN_INIT_WIDTH = 1280;
    unsigned int const SCREEN_INIT_HEIGHT = 720;
    unsigned int const TILESIZE = 32;

    //void CORE_Init(); // replace this one with constructor:
    GameCore();

    //to properly clean up objects you created inside:
    ~GameCore(); // destructor 
};
现在,您可以根据需要将访问这些GUI元素的所有其他函数也转换为成员函数,有些是公共函数,有些是私有函数。然后您将创建如下GUI:

int main()
{
    GameCore gc; // or possibly with parametrised: GameCore gc(7, 10, 12);

    // and use it from within main, e. g. simply:
    return gc.run();
}
如果您仍然坚持从不同的源访问全局变量,那么您确实依赖于
extern
关键字(但仍然使用include-guard!)


旁注:在旧的(过时的)C宏(<代码> null < /代码>)下,您应该更喜欢C++关键字(<代码> NulLPTR < /代码>)——除非明确地为不支持至少C++ 11的旧环境编写代码。这能回答你的问题吗?是的,我这样做了,但它给了我多个定义错误。我有一个名为GAMixCype的头文件。H和I包含在MIN .CPP中,并且在另一个头文件中,我也包含在其中。“……显示了GWindows、GrEnDER、GWIDWORD和Debug字体的多个定义”——您不能在头文件中指定命名空间变量,考虑使用<代码> EnUM < /COD>全局整数类型常量。

class GameCore
{
    // depends on how they are created, maybe std::unique_ptr is more appropriate?
    // you might avoid necessity of a destructor
    SDL_Window* m_window;
    SDL_Renderer* m_renderer;
    SDL_Surface* m_windowSurface;
    TTF_Font* m_defaultFont; // maybe rather a static constant?

public:
    // constants can easily be public:
    unsigned int const SCREEN_INIT_WIDTH = 1280;
    unsigned int const SCREEN_INIT_HEIGHT = 720;
    unsigned int const TILESIZE = 32;

    //void CORE_Init(); // replace this one with constructor:
    GameCore();

    //to properly clean up objects you created inside:
    ~GameCore(); // destructor 
};
int main()
{
    GameCore gc; // or possibly with parametrised: GameCore gc(7, 10, 12);

    // and use it from within main, e. g. simply:
    return gc.run();
}
// header file:

#ifndef SOME_GUARD_NAME
#define SOME_GUARD_NAME
namespace GAME_CORE
{
extern SDL_Window* gWindow; // no assignment!
// ...
}
#endif

// source file:

// you still need a definition in EXACTLY ONE compilation unit:
SDL_Window* GAME_CORE gWindow = nullptr;