0

I'm a newcomer to C++. I'm having trouble building a simple multi-file project with g++. Here are my files:

something.h

class Something
{
public:
    void do_something() const;
} thing;

something.cpp

#include <iostream>
#include "something.h"

void Something::do_something() const
{
    std::cout << "Hello!" << std::endl;
}

main.cpp

#include "something.h"

int main()
{
    thing.do_something();
}

Here is what I tried:

  • g++ main.cpp gives an error that do_something is an undefined reference, which makes sense because the compiler has no idea something.cpp has anything to do with something.h.

  • g++ main.cpp something.cpp: there are 'multiple definitions' of thing, even though I clearly defined it only once.

  • g++ -c main.cpp something.cpp: no errors! However, when I try running g++ *.o it gives me the same error as above, so I'm thinking this is a linker error.

Can anyone explain how to compile a multi-file project, and why my approach isn't working? I'm pretty confused right now because above is what most of the C++ examples on Stack Overflow look like.


Sidenotes:

  • I did try the suggestions here, but they didn't address linking issues with headers specifically.

  • I'm not trying to redefine thing in main; if I wanted to do that, I would have typed up Something thing.

Community
  • 1
  • 1
James Ko
  • 32,215
  • 30
  • 128
  • 239
  • Do you know what 'thing' after the } does? –  Jul 23 '15 at 00:32
  • @CamelToe It creates a global variable called `thing`? At least that's what I was taught [here](http://www.cplusplus.com/doc/tutorial/structures/). – James Ko Jul 23 '15 at 00:34
  • @Barmar I don't believe I'm redefining the global variable as in a `Something thing;` statement, I'm just trying to use it. – James Ko Jul 23 '15 at 00:35
  • Since you have `#include "something.h"` in both `.cpp` files, that will try to define the variable in both of them. That's a redefinition. – Barmar Jul 23 '15 at 00:37
  • Ok, do you know how the file is going to look like when everything is getting linked together? Replace every include with the source from the file and you'll get a hint –  Jul 23 '15 at 00:40
  • @Barmar Ah, so does that mean I have to add something like `#pragma once` to the header to prevent it from being re-pasted by the compiler? – James Ko Jul 23 '15 at 00:40

2 Answers2

3

g++ main.cpp gives an error that do_something is an undefined reference, which makes sense because the compiler has no idea something.cpp [...]

... which contains the definition of the member function do_something exists. So you reference an undefined function.

g++ -c main.cpp something.cpp: no errors! [...]

... since you're only compiling the files, not linking them together.

When you link them together, you end up with

[...] 'multiple definitions' of thing [...]

which is exactly what you're doing:

class Something {
  // content
} thing;

is the same as

class Something {
 // content
};

Something thing;

And since #include "something.h" works by effectively copying the contents of the included file right into the including file, you end up with 2 files with a line

Something thing;

in each of them. And this is what the linker (called from the compiler frontend) is telling you: There are multiple definitions of the global variable thing.

To solve this: Don't put definitions for global variables into header files, only declarations:

extern Something thing;

And then add a definition in a single source file:

Something thing;

Or, better, try to avoid global variables.


One more thing: If you aren't doing it already, use include guards for your headers.

Daniel Jour
  • 15,896
  • 2
  • 36
  • 63
0

make sure you have added all files to the project. Like if you are using IDE e.g, DEV C++ you have to add each .cpp or .h file to the project.