Reputation: 53597
I have the following code:
#ifndef GOOGLESET_PHP_H
#define GOOGLESET_PHP_H
zend_class_entry *googleset_ce;
#endif /* GOOGLESET_PHP_H */
For some reason if I include this header file in more than one cpp file, the compiler shouts that I am declaring googleset_ce
more than once. Shouldn't the conditional macros above be enough to avoid this?
Upvotes: 3
Views: 10521
Reputation: 11
instead of using "#ifndef GOOGLESET_PHP_H
#define GOOGLESET_PHP_H
#endif /* GOOGLESET_PHP_H */"
you can use
#pragma once
Upvotes: 1
Reputation: 6962
Beware that it is a linker error, not a compiler error. You get a multiple defined symbol when the linker tries to put together the object files (*.o
) for all the *.cpp
files including the header file.
You would probably work around the problem using the extern
keyword to make the symbol unique. And declaring it somewhere else in one (and only one) .cpp
file.
Upvotes: 2
Reputation: 26943
yes, but you are only declaring it once per compilation unit.
include guards only make sure you declare things once per .cpp that uses it.
So if A.h
is included in B.h
and impl.cpp
includes both, then A.h
is included only the first time.
In your case, you are defining the value of the include guard macro as a static pointer variable. So even if impl.cpp
has it only once, impl2.cpp
which includes the same files will have them as well, so your static variable will have duplicate definitions at link-time
if you insist in having static variables (as Thomas said, it is usually bad design) it is better to wrap them in a function;
myClass* getInstance() {
static myClass instance;
return &instance;
}
this is slightly better because it makes sure the variable is truly global, some architectures (like darwin) have that static
variables are unique per dynamic library, not per process, so it might led to confusing behavior/portability
Also, and more relevant, static initialization always happens before main, and the order is not guaranteed. With static function variables, the variables are initialised "on demand" and so it is not affected by initialization ordering issues
to initialise a global pointer:
myClass** getGlobalRef() {
static myClass* val;
return &val;
}
//and you set it at run-time, avoiding static-initialization happening before main
* getGlobalRef() = new myClass();
Upvotes: 5
Reputation: 3100
lurscher has the answer. If you're looking to share the same global variable across .cpp files, one way to do it is to declare it globally in one of your .cpp files, then declare it as extern inside the header file.
For example:
main.cpp
zend_class_entry *googleset_ce = NULL;
googleset.h
#ifndef GOOGLESET_PHP_H
#define GOOGLESET_PHP_H
extern zend_class_entry *googleset_ce;
#endif /* GOOGLESET_PHP_H */
Upvotes: 0
Reputation: 57678
You need to use the extern
keyword:
#ifndef GOOGLESET_PHP_H
#define GOOGLESET_PHP_H
extern zend_class_entry * googleset_ce;
#endif // GOOGLESET_PHP_H
Otherwise the compiler thinks you are declaring the variable in every file that includes this header.
This is one reason global variables are frowned upon.
Upvotes: 7
Reputation: 2189
If the header is included in several .c/.cpp files then indeed it's potentially declared in multiple .obj files. You have to encapsulate it in a namespace or a class so it's not considered as a global variable for each .cpp file that includes it.
Upvotes: 0