Itay Moav -Malimovka
Itay Moav -Malimovka

Reputation: 53597

how to avoid duplicate inclusion of a header file

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

Answers (6)

Kumaresh Mishra
Kumaresh Mishra

Reputation: 11

instead of using "#ifndef GOOGLESET_PHP_H

             #define GOOGLESET_PHP_H 

            #endif /* GOOGLESET_PHP_H */" 

you can use

           #pragma once

Upvotes: 1

Antonio Pérez
Antonio Pérez

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 *.cppfiles 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

lurscher
lurscher

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

JoeFish
JoeFish

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

Thomas Matthews
Thomas Matthews

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

azf
azf

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

Related Questions