0

I defined the following structure to be used across the application by several classes.

ZHTypes.h

#ifndef ZHTypes_h
#define ZHTypes_h

struct BeingHitParams
{
    bool isApplyKnockBack=true;
};
BeingHitParams *default_BeingHitParams_ptr = new BeingHitParams();

#endif

I defined a following variable

default_BeingHitParams_ptr

for the case the I will use it in several places for default parameters of function as I don't need to create a new structure all the time.

Anyway, the above defined variable produces linking error whenever I refer to it in the code inside a class. But if I add static in front then it works fine.

static BeingHitParams *default_BeingHitParams_ptr = new BeingHitParams();

So my question is why can't we access global but non-static variable from within a class? I also want to know additional explanation of why C++ is restricted in accessing variable like in the situation above.

haxpor
  • 2,431
  • 3
  • 27
  • 46
  • 3
    The `BeingHitParams *default_BeingHitParams_ptr = new BeingHitParams();` part belongs into a cpp file, not a header. – Micha Wiedenmann Mar 07 '13 at 13:37
  • 3
    Don't define globals in header files. – LihO Mar 07 '13 at 13:37
  • 5
    or yet even better: avoid using globals completely if possible. – LihO Mar 07 '13 at 13:38
  • Some thoughts about global in c++. http://stackoverflow.com/questions/544462/global-variables-and-scope-c –  Mar 07 '13 at 13:40
  • @RobertP. I'm not sure I'd say the top answer there gave a *better* solution. It still has all the problems of global state. – Joseph Mansfield Mar 07 '13 at 13:41
  • @sftrabbit - only some thoughts - no rating ;-) –  Mar 07 '13 at 13:52
  • 1
    Why use globals? Why put them in a struct? Why use a pointer? Why the dynamic allocation? Did you use to write a lot of Java? :-) – Bo Persson Mar 07 '13 at 13:59
  • @Liho Any difference if we define it via #define (in general case) ? – haxpor Mar 07 '13 at 14:07
  • 1
    @haxpor: `#define` is directive for preprocessor.. it's just a textual replacement within your code before it is compiled. `#define` is even worse than `const` global, because you lose information about the type of your constant. `BeingHitParams* default_BeingHitParams_ptr` doesn't seem to be a constant though. – LihO Mar 07 '13 at 14:10
  • I use it to access global settings like attack points, distance knock-off, sfx path, etc I think pack it up in one single file would give flexibility. Can you suggest the better way? – haxpor Mar 07 '13 at 14:13
  • @Bopersson I use struct pointer with a thought that I don't need to do any shallow or deep copy every time I pass through functions. Thanks for mentioning about dynamic allocation, I guess it's not necessary. – haxpor Mar 07 '13 at 14:18
  • I have defined configurations and settings via #define a lot packing in a single header file and it's accessed by other game object classes. Is that a bad design? Is there a better way to do it? (I just feel this comment question is still relating to the main question. It's my last question in comment section here.) – haxpor Mar 07 '13 at 14:35

1 Answers1

6

If you put static in front of it then you are giving it internal linkage and each translation unit that includes that header has their own copy of default_BeingHitParams_ptr. What you actually want to do is declare it extern in the header file (which not only makes it have external linkage but also makes it a declaration rather than a definition) and then define it in a single translation unit:

// ZHTypes.h
// Now this is just a declaration:
extern BeingHitParams *default_BeingHitParams_ptr;

// ZHTypes.cpp
// Defined in a single translation unit:
BeingHitParams* default_BeingHitParams_ptr = new BeingHitParams();

However, introducing global state is usually a bad thing.

Joseph Mansfield
  • 108,238
  • 20
  • 242
  • 324
  • @sftrabbit Can't #ifndef prevent the multiple translation unit (as per your explanation)? – haxpor Mar 07 '13 at 14:40
  • 1
    @haxpor `#ifndef` inclusion guards only prevent a header from being included multiple times in a *single* translation unit. You almost certainly *want* a header to be included across multiple translation units. – Joseph Mansfield Mar 07 '13 at 14:42