【问题标题】:Declaring global structures in header files in C++在 C++ 的头文件中声明全局结构
【发布时间】:2012-07-11 16:14:01
【问题描述】:

我在头文件中创建了如下结构:

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 文件的一部分?

【问题讨论】:

  • 始终显示第一个错误的全文。在 Visual Studio 中,这可以在“输出”窗口中找到,而不在在“错误”窗口中。

标签: c++ opengl global-variables declaration structure


【解决方案1】:

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都定义的。

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

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

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

【讨论】:

  • 哇。不敢相信我没有意识到这一点。谢谢。至于其他的,非常有用,谢谢!
【解决方案2】:
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 文件的一部分?

是的,以上两种解决方案都是这样做的。

然而,最后一个是向每个编译单元注入一个引用,实际上是指针的大小。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-02-13
    • 1970-01-01
    • 2016-06-27
    • 2021-12-28
    • 2012-04-05
    • 2023-03-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多