在C++中声明头文件中的全局结构

Declaring global structures in header files in C++

本文关键字:全局 文件 结构 C++ 声明      更新时间:2023-10-16

我在头文件中创建了一个结构,如下所示:

typedef struct
{
    GLfloat lgtR, lgtG, lgtB, lgtA;
    GLfloat x, y, z;
    bool islight;
    GLfloat width, height, depth;
    GLenum lightn;
    particle prt;
    int maxprt;
} emitter;

其工作没有问题。

然而,在那个特定的头文件中,我想声明一个全局发射器,我可以在所有函数中使用它,而不是主源文件的一部分:

// header.h global declaration
emmiter currentEmit;
GLvoid glSetEmitter(emitter emitter)
{
    currentEmit = emitter;
}

然而,当我尝试这样做时,我会得到很多"错误C2228:'.variable'的左边必须有类/结构/并集,所以我假设它根本没有在这里声明我的结构。

有没有办法在头文件中全局声明该结构?如果有,还有没有办法防止它成为其他.cpp文件的一部分?

emitteremmiter不同。

此外,由于这是C++-只需直接写入struct {};,因此不需要typedef

你的整个标题是错误的,如果包含在多个翻译单元中,会给出多个定义:

// header.h global declaration
extern emitter currentEmit;   // <-- note extern
inline GLvoid glSetEmitter(emitter emitter)  // <-- note inline
{
    currentEmit = emitter;
}

currentEmit需要在单个实现文件中定义,而不是在头中定义。该函数需要是inline,因此它不是由所有TU定义的。

最后一件事:通过常量引用传递参数:

inline GLvoid glSetEmitter(const emitter& emitter)  // <-- note inline
{
    currentEmit = emitter;
}

否则将创建不必要的副本。

typedef struct
{
    GLfloat lgtR, lgtG, lgtB, lgtA;
    GLfloat x, y, z;
    bool islight;
    GLfloat width, height, depth;
    GLenum lightn;
    particle prt;
    int maxprt;
} emitter;

最好是

struct Emitter
{
    GLfloat lgtR, lgtG, lgtB, lgtA;
    GLfloat x, y, z;
    bool islight;
    GLfloat width, height, depth;
    GLenum lightn;
    particle prt;
    int maxprt;
};

有没有一种方法可以在头文件中全局声明该结构

是的,有两种主要方法可以避免在每个编译单元中创建变量。

首先是Meyers的单例:

namespace g {
    inline Emitter& emitter()
    {
        static Emitter theEmitter;
        return theEmitter;
    }
}
void foo() { g::emitter().x = 666; }

然后是模板化技巧:

namespace detail {
    template< class Dummy >
    struct EmitterVariable
    {
        static Emitter v;
    };
    template< class Dummy >
    Emitter EmitterVariable<Dummy>::v = {};
}
namespace g {
    static Emitter& emitter = EmitterVariable<void>::v;
}
void foo{ g::emitter.x = 666; }

如果是这样的话,是否还有一种方法可以防止它也成为其他.cpp文件的一部分?

是的,上述两种解决方案都能做到这一点。

然而,最后一个将一个引用注入到每个编译单元中,在实践中,该引用的大小相当于一个指针。

也就是说,全局变量往往会给出非常混乱的数据流。你不知道代码的哪一部分放了一些东西。您不知道它是否或何时正确初始化。如果您更改此处的数据,您不知道哪些其他部分会受到影响。或者什么时候。等等。所以这绝对不是一个好主意。全局常量,可以,但全局variables、Just Say No™。