0

I have a util.h containing a function which will be used in a.h and 'b.h', and further more, a.h and b.h will include each other in order to access some classes defined in each other.

//util.h

#ifndef _UTIL_H_
#define _UTIL_H_

#include <iostream>

void foo()
{
    std::cout << "foo\n";
}

#endif

//a.h, it has a a.cpp
#ifndef _A_H_
#define _A_H_

#include "util.h"
#include "b.h"

//some classes' definition

#endif

//b.h, it has a b.cpp
#ifndef _B_H_
#define _B_H_

#include "util.h"
#include "a.h"

//some classes' definition

#endif

My problem is that, I got multiple definition error for foo. How?

I thought the problem might be that, a.h includes util.h and b.h, and b.h includes util.h once again, so I got multiple def error. But it can't seem to make sense, because in util.h I wrote #ifndef/#define guards.

Anyone can give me a help, thanks.

Alcott
  • 17,905
  • 32
  • 116
  • 173
  • 1
    Multiple definitions is a link-time error, and shouldn't have to do with your header files (which have declarations, not definitions). How are you compiling? – Gordon Bailey Aug 09 '12 at 03:44
  • @GordonBailey, I just compile it the usual way, like `g++ main.cpp a.cpp b.cpp`. – Alcott Aug 09 '12 at 03:49
  • 1
    it should be `static void foo() { /* body */ }`, if you want to put the function body in the header. – user2k5 Aug 09 '12 at 03:56
  • Symbols starting with an underscore and double underscore are reserved by implementation. Use something like `UTIL_H_` for the header guards. – Sanish Aug 09 '12 at 04:22

1 Answers1

6

Your problem is caused by defining rather than simply declaring foo inside utils.h

For this example, assume that we have:

a.cpp

#include "a.h"

b.cpp

#include "b.h"

main.cpp

#include "a.h"
#include "b.h"
#include "utils.h"


int main(){
    foo();
    return 0;
}

After preprocessing, but before compilation, your files now look like this (this is a simplification, but you get the idea):

a.cpp

void foo()
{
    std::cout << "foo\n";
}

b.cpp

void foo()
{
    std::cout << "foo\n";
}

main.cpp

void foo()
{
    std::cout << "foo\n";
}

int main(){
    foo();
    return 0;
}

Now when you compile, you have 3 definitions of foo (they're all identical, but this is irrelevant). After compilation, there is no way for the linker to know which definition to pick for any given call to foo and so it generates an error.

Instead of defining foo in the header, define it in utils.cpp and only put a declaration in utils.h, e.g.

utils.h

#ifndef _UTIL_H_
#define _UTIL_H_

void foo();

#endif

or, alternately, declare foo as static or inline:

utils.h

#ifndef _UTIL_H_
#define _UTIL_H_

static void foo()
{
    std::cout << "foo\n";
}

/* OR */

inline void foo()
{
    std::cout << "foo\n";
}


#endif

This is something you need to do only if you want to inline your function. In this case, the compiler needs a definition of the function in every translation unit where it is used, as it essentially becomes a compile-time macro.

Gordon Bailey
  • 3,881
  • 20
  • 28
  • Nicely explained: +1 =) Just a subtle point I'd make... It's true that normally you would declare the function in a header and define it in a source file, but there are times when you might define the function in a header - and that is when providing inlined functions for speed: `inline void foo() { std::cout << "foo\n"; }`. An utterly pointless thing to do in this case, however! – paddy Aug 09 '12 at 04:07
  • So, by `inline` the compiler will treat `foo` as `static`? – Alcott Aug 10 '12 at 08:08