3

I have the following 3 files:

error.h

#ifndef error_h
#define error_h
#include <string>
#include <iostream>
#include <cstdio>
void Error(std::string msg);
#endif

error.cpp

#ifdef error_h
#include "error.h"
void Error(std::string msg)
{
    std::cerr
     << "\n=========================================================\n"
     << msg
     << "\n=========================================================\n";
    exit(EXIT_FAILURE);
}
#endif

foobar.cpp

#include "error.h"
int main()
{
    for(int i=0; i<99; i++)
        if(i==55)
            Error("this works");
    return 0;
}

Now I do:

$ g++ -c error.cpp foobar.cpp
$ g++ error.o foobar.o -o exampleprogram

And I get:

foobar.o: In function `main':
foobar.cpp:(.text+0x4b): undefined reference to `Error(std::basic_string<char,
std::char_traits<char>, std::allocator<char> >)'
collect2: ld returned 1 exit status

What am I doing wrong? What do I need to understand to resolve this, and similar issues in the future without asking questions? Thanks!

user1358
  • 623
  • 2
  • 8
  • 13

3 Answers3

4

Why do you have these lines in error.cpp?

#ifdef error_h
  ...
#endif

Since the preprocessor symbol error_h is not defined the entire contents of error.cpp are being omitted by the preprocessor. Remove those lines and your program will link successfully.

You seem to have a misunderstanding of how (and maybe why) #include guards are to be used. Refer to this answer for an explanation.

Also, there's no need to include iostream and cstdio in error.h, since that file is not using anything declared in either of those headers. Those files should be included in error.cpp.

Community
  • 1
  • 1
Praetorian
  • 106,671
  • 19
  • 240
  • 328
  • Thank you! I have been doing a lot of ".cpp including" of template implementations lately and I just typed these without thinking and overlooked them the whole time. You mentioned iostream and cstdio includes... does this mean that I have to scatter around some of the includes? Some in the .h and some in the .cpp? Is #include needed by the function prototype? Isn't there a way of bundleing all the includes for a .h and .cpp in general? Thanks again. – user1358 Aug 05 '12 at 18:10
  • 1
    @user1358 Best practice is to only include the headers that are actually needed in that file, so yes, includes tend to be scattered around. There's nothing incorrect about including both the headers in *error.h*, but when you include *error.h* in *main.cpp*, the preprocessor will include the files in the translation unit created from *main.cpp* and the compiler will have to process those headers as well. Not really a concern in small projects, but for large projects this can significantly impact build times. – Praetorian Aug 05 '12 at 18:16
  • Your explanations helped a lot. Thank you very much. – user1358 Aug 05 '12 at 18:24
2

Remove this

#ifdef error_h

and the corresponding #endif from error.cpp. Otherwise, here:

$ g++ -c error.cpp foobar.cpp

error.cpp is essentially empty. This is because at that stage error_h is not defined. So you are not compiling the implementation (it would work if you had included error.h before the #ifdef, but there is no reason to have that in the .cpp file anyway).

juanchopanza
  • 223,364
  • 34
  • 402
  • 480
2

error_h is not defined in error.cpp, so all your file content gets #ifdef'd away.

In essence, you're compiling error.cpp as an empty file.

Joachim Isaksson
  • 176,943
  • 25
  • 281
  • 294