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.

4
  • 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? Commented Aug 9, 2012 at 3:44
  • @GordonBailey, I just compile it the usual way, like g++ main.cpp a.cpp b.cpp. Commented Aug 9, 2012 at 3:49
  • 1
    it should be static void foo() { /* body */ }, if you want to put the function body in the header. Commented Aug 9, 2012 at 3:56
  • Symbols starting with an underscore and double underscore are reserved by implementation. Use something like UTIL_H_ for the header guards. Commented Aug 9, 2012 at 4:22

1 Answer 1

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.

Sign up to request clarification or add additional context in comments.

2 Comments

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!
So, by inline the compiler will treat foo as static?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.