Reputation: 162
I've created a structure in a header file as follows:
typedef struct
{
GLfloat lgtR, lgtG, lgtB, lgtA;
GLfloat x, y, z;
bool islight;
GLfloat width, height, depth;
GLenum lightn;
particle prt;
int maxprt;
} emitter;
which works without a problem.
However, in that particular header file, I want to declare a global emitter that I can use in all the functions and isn't part of the main source file:
// header.h global declaration
emmiter currentEmit;
GLvoid glSetEmitter(emitter emitter)
{
currentEmit = emitter;
}
However, when I do try this, I get a whole lot of "error C2228: left of '.variable' must have class/struct/union, so I'm assuming it's not declaring my structure here at all.
Is there a way to declare that structure globally within a header file, and if so, is there also a way to keep it from being part of the other .cpp files as well?
Upvotes: 0
Views: 1739
Reputation: 145457
typedef struct
{
GLfloat lgtR, lgtG, lgtB, lgtA;
GLfloat x, y, z;
bool islight;
GLfloat width, height, depth;
GLenum lightn;
particle prt;
int maxprt;
} emitter;
should better be
struct Emitter
{
GLfloat lgtR, lgtG, lgtB, lgtA;
GLfloat x, y, z;
bool islight;
GLfloat width, height, depth;
GLenum lightn;
particle prt;
int maxprt;
};
Is there a way to declare that structure globally within a header file,
Yes, there are two main ways to avoid the variable being created in each compilation unit.
First there is the Meyers' singleton:
namespace g {
inline Emitter& emitter()
{
static Emitter theEmitter;
return theEmitter;
}
}
void foo() { g::emitter().x = 666; }
Then there is the templatization trick:
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; }
and if so, is there also a way to keep it from being part of the other .cpp files as well?
Yes, both of the above solutions do that.
The last one, however, injects a reference into each compilation unit, which in practice will be the size of a pointer.
That said, global variables tend to give very messy data flows. You don't know which part of the code put something there. You don't know if or when it's properly initialized. You don't know which other parts will be affected if you change data here. Or when. And so on. So it's absolutely not a good idea. Global constants, OK, but global variables, Just Say No™.
Upvotes: 1
Reputation: 258698
emitter
is not the same as emmiter
.
Also, since this is C++ - just write struct {};
directly, there's no need for a typedef
.
Your whole header is wrong, and will give multiple definitions if included in multiple translation units:
// header.h global declaration
extern emitter currentEmit; // <-- note extern
inline GLvoid glSetEmitter(emitter emitter) // <-- note inline
{
currentEmit = emitter;
}
currentEmit
needs to be defined in a single implementation file, not a header. The function needs to be inline
so it's not defined by all TU.
Last thing: pass the parameter by const reference:
inline GLvoid glSetEmitter(const emitter& emitter) // <-- note inline
{
currentEmit = emitter;
}
Otherwise an unnecessary copy will be created.
Upvotes: 7