2

Getting a LNK2005 "already defined in GUI.obj" for a function pointer in PAL.h

//GUI.cpp
#include "PAL.h"

//PAL.h
#define PAL_INCLUDE
int (*addPAL)( int, void(*)(), void(*)() );

//main.cpp
#include "GUI.h"
#ifndef PAL_INCLUDE
#include "PAL.h"
#endif

Have I misunderstood the nature of includes and #ifndef?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
spinning
  • 119
  • 1
  • 1
  • 10

4 Answers4

5

You're getting the error probably because the preprocessor is processing main.cpp before GUI.cpp. Try changing the content of your PAL.h to this:

 #ifndef PAL_INCLUDED
 #define PAL_INCLUDED
 // definitions
 #endif

Reference

Include guard

Cyclonecode
  • 29,115
  • 11
  • 72
  • 93
3

I think you should use the include guard over PAL.h.

If I understand what you're trying to do, this code is much more clear (and quite common out there):

GUI.h

#ifndef _GUI_H_
#define _GUI_H_
...
#endif

GUI.cpp

#include "PAL.h"
...

PAL.h

#ifndef _PAL_H_
#define _PAL_H_

int (*addPAL)( int, void(*)(), void(*)() );

#endif

main.cpp

#include "GUI.h"
#include "PAL.h"
...

Hope it helps.

frarees
  • 2,190
  • 3
  • 17
  • 22
  • Include guards are a good idea, but he's getting a link error for defining addPAL twice – Joseph Stine Nov 30 '11 at 23:37
  • And he's doing because his compiler is probably compiling all the sources before `main.cpp`, and he has more than one `cpp` file including `PAL.h`. That way, everytime he's including `PAL.h` he's redefining `addPAL`, so I think we're talking about the same thing. – frarees Nov 30 '11 at 23:45
  • The two GUI.cpp and main.cpp are compiled separately (order is irrelevant) and then at link time the compiler finds two definitions of addPAL, because PAL.h is included in each. Include guards only prevent a .h from being included multiple times within one .cpp file – Joseph Stine Nov 30 '11 at 23:51
  • I may be wrong, but I thought order does matter. As far as I know, whenever a `#define` preprocessor directive is found by the compiler, its definition is pushed to the symbol table, so any conditional preprocessor directive (`#ifndef`) looks up in that table to resolve. That way, makes sense that order influences when your definitions/implementations are not properly safeguarded. – frarees Dec 01 '11 at 00:17
3

Main.cpp and GUI.cpp are compiled separately from each other and then linked together. This means the preprocessor state is reset between the two compiles, and you lose the definition of PAL_INCLUDE
Header guards stop a header from being included more than once by other headers in the same compile unit, not to prevent clashes in the linker.

Try putting static in front of the method declaration - it limits the function to the current unit, thus preventing this problem. For more information, see What is a “static” function?

Community
  • 1
  • 1
Lexi
  • 1,670
  • 1
  • 19
  • 35
2

addPal is getting defined twice, once in GUI.cpp and once in main.cpp. What you want is to define it once and declare it everywhere you need to use it. I suggest putting

int (*addPAL)( int, void(*)(), void(*)() );

in one of the .cpp files (I haven't seen enough code to decide which one it belongs in), then the declaration:

extern int (*addPAL)( int, void(*)(), void(*)() );

in the header file. The extern tells the compiler that the pointer addPAL exists, but is defined elsewhere

Joseph Stine
  • 1,022
  • 1
  • 12
  • 23