5

I have header util.hpp containing a simple struct:

// util.hpp

struct Point {
  float x;
  float y;
};

Two cpp files, let's call them a.cpp and b.cpp, both include util.hpp:

// a.cpp

#include "util.hpp"

void funcA(float _x, float _y) {
  Point p;
  p.x = _x;
  p.y = _y;
  // ...
}
// b.cpp

#include "util.hpp"

void funcB(float _x, float _y) {
  Point p;
  p.x = _x;
  p.y = _y;
  // ...
}

int main() {
  // ...
}

When I compile a.cpp and b.cpp individually and then link them together I get no errors.

Why is that? Since I include util.hpp in both files, wouldn't we have a double definition of struct Point? When I for example add a variable definition to util.hpp like this:

// util.hpp

struct Point {
  float x;
  float y;
};

// New variable
int foo;

I get the following error when linking:

g++ a.o b.o -o test -O0
b.o:(.bss+0x0): multiple definition of `foo'
a.o:(.bss+0x0): first defined here

which makes sense to me, but why doesn't the same error occur for the struct?

Amplify
  • 865
  • 1
  • 8
  • 18

2 Answers2

6

b.o:(.bss+0x0): multiple definition of `foo'

having

// util.hpp
...
// New variable
int foo;

each time you include util.hpp you define again the global variable foo, producing your error

in the header file just declare it (extern int foo;) and define it on one source file

There is not the same problem for the struct Point because this is a type definition, not a global variable definition

bruno
  • 32,421
  • 7
  • 25
  • 37
5

A type definition (struct, union, class, enum) is just kind of a "blueprint" for the compiler how to lay out certain things in memory but don't cause the generation of code or symbols on their own.

In C++ you can also have member functions and operators and static member variables, however these are technically not part of the struct/class but come with the struct/class and as such you can globally define them only once.

And just like that global variable definition of foo you have there this doesn't work if done in a file included multiple times. But you can safely declare them multiple times.

datenwolf
  • 159,371
  • 13
  • 185
  • 298
  • So a multiple _type_ definition is allowed? Does the linker recognize that it's the same struct in both object files? – Amplify Jul 07 '19 at 13:37
  • 1
    @Kittion: No, multiple type definitions are not allowed inside a single compilation unit. What happens is, that type definitions by themself do not emit anything. And because there's nothing emitted there's nothing for the linker to complain about. – datenwolf Jul 07 '19 at 13:52