简体   繁体   中英

Header and unresolved external symbol

I'm just starting to learn C++ and cannot understand how I need to use header file. I've seen and read some of existing answers over Stack Overflow but still didn't manage to understand well. I wrote this code and it give me Unresolved Externals error.

Sum.h

#ifndef SUM
#define SUM

int add(int x, int y, int z);

#endif

Sum.cpp

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

int add(int x, int y, int z)
{
    return x + y + z;
}

Main.cpp

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

int main()
{
    using namespace std;
    cout << "3 + 4 + 5 = " << add(3, 4, 5) << endl;
    return 0;
}

How do I solve this problem so my code can run?

Thanks!

EDIT: Forgot to add, I'm using Microsoft Visual Studio Express 2013 for Windows Desktop.

I assume you are trying to run the program like this:

g++ main.cpp
./a.out

The problem is that even though your program will compile, it won't "link". What is happening is that the linker is not able to find the code for "add(int, int, int)". To remedy this, you need to specify all the files that are part of your compilation. Try this:

g++ main.cpp sum.cpp
./a.out

In the first case, although your sum.h file is directly included, because there is a pre-processor specification asking for it to be imported. Then, main.cpp compiles, but the output does not contain that code for the add function. The output simply says that "call a function called add on these numbers". The compiler tells the linker that it is the linker's responsibility to find the function when it is finally converting it all to an executable. Then when the linker runs, it is not able to find any method "add" which the output of "main.cpp" was referring to. As a result, it throws an error.

In the second case, both the files are compiled, (generally to a .o file), which contains the code for all that is contained within them. Now when the linker tries to link it all, it can easily find the add method because it has the .o file to work with. Try this to help you understand how this process works:

g++ -c main.cpp

This will compile the main.cpp to a main.o file. Do a ls in your directory to see this file. The -c option asks the compiler to skip the linking process and to ONLY compile the source file. Then, do this:

g++ -c sum.cpp

If you take a look again, you will find that there is a file called sum.o . So you have basically converted your code in text to binary which is an intermediate format. Most of the validations, type-checking, syntax checking etc. have been performed by now and the main.o and sum.o are effectively files that represent steps to perform a certain computation. Do note that the compiling step does not require a main method to work. It is just transforming instructions from one format to another. It is required when you build an executable, because you of course need to know what exactly you should execute when you run the executable. To get your final executable, you just need to do this:

g++ -o myexec.out sum.o

Oops.. you see an error here. What does it say? undefined reference to main . This confirms what we previously thought when we said that the linker needs a "main" function to link to, otherwise it won't know where to start when the executable is run. Let us give it the main function:

g++ -o myexec.out sum.o main.o

And.. there you go.. It compiled. The -o switch just tells g++ what the output executable should be called. To run your program, just do:

./myexec.out

And that is all... Once you get comfortable around this, you would like to venture into Makefiles and autotools. Real-life projects have thousands and thousands of C++ files which are compiled in similar ways, but it gets really difficult to manage once you move into double-digit file numbers. So, we use tools like make to simplify this process and make it highly configurable. Hope this helps you begin!

EDIT#2

Thought I would quickly drop in the need for a .h file. A compiler processes only file at a time. So, when it is processing main.cpp, and it comes across something called add(4, 5, 1) , it doesn't know what add is. For all it knows, it could be a variable int add = 10 and I would be using it incorrectly. How does a compiler verify this? The sum.h file helps it with that, and in the process helps us as well. The .h file just tells the compiler what kind of a symbol add is. If you try to make another file called sum2.cpp and in there define add as add(int x, int y) instead of the 3-variable function, both your files will compile file, but the linking will still fail. This is because the linker is looking for a symbol add(int, int, int) whereas what it sees is add(int, int) . The compiler only verifies your code against the definitions you throw at it.

If you were to remove the #include "sum.h" statement from the first line and just replace it with int add(int x, int y, int z); , and follow all the steps as written above, it will still work. However, the reason we define it in a separate file is so that changes become easier for us to manage. In this case, even though sum.cpp and main.cpp are compiling separately, they are being compiled against the same definition, which keeps us all in check. There is only one place of definitions, which acts as the source of truth and that ensures that both sum.cpp and main.cpp are in sync.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM