I can't get my head around headers and header guards. I've read other questions and their answers but I still can't make this work in Visual Studio 2013:
main.cpp
#include "stdafx.h"
#include <iostream>
#include "add.h"
int _tmain(int argc, _TCHAR* argv[]) {
std::cout << "3 + 4 = " << add(3, 4) << std::endl;
system("pause");
return 0;
}
add.cpp
#include "stdafx.h" //ADDED LATER; NOW WORKING (AND SEE QUESTION 2 BELOW)
#include "add.h" //ADDED LATER; NOR WORKING (AND SEE QUESTION 2 BELOW)
int add(int x, int y) {
return x + y;
}
add.h
#ifndef ADD_H
#define ADD_H
int add(int x, int y);
#endif
When I compile, the console window flashes on-screen then disappears. The Error List contains:
Error 1 error LNK2019: unresolved external symbol "int __cdecl add(int,int)" (?add@@YAHHH@Z) referenced in function _wmain c:\Users\Danny\documents\visual studio 2013\Projects\Addition Program\main\main.obj main
Error 2 error LNK1120: 1 unresolved externals c:\users\danny\documents\visual studio 2013\Projects\Addition Program\Debug\main.exe main
1. How do headers and header guards work? I see how by #including add.h
, it makes main.cpp
aware of the declaration of add(int x, int y)
, but then how does it find its definition?
2. What have I got wrong in my code?
My code is compiling now. The reason my code wasn't compiling was because I had been going File > New > File... to add files to my project, as opposed to adding them through the Source Files and Header Files sections of the Solution Explorer in Visual Studio. I also needed to add #include "stdafx.h
to the add.cpp file.
Think of it this way: each
.cpp
file is preprocessed and then compiled completely separately from the other files.So let's first preprocess
main.cpp
. This involves looking at all the lines beginning with#
. The filemain.cpp
only has#include
lines, which simply copy the contents of the file they're including. I'm going to represent the contents ofstdafx.h
andiostream
with a comment, but I'll actually copy the contents ofadd.h
in:See now that the contents of
add.h
have been brought intomain.cpp
? And it so happens that this has brought in some more preprocessor directives, so we'll need to do what they say. The first checks ifADD_H
is not defined yet (in this file), which it is not, and so leaves everything up until the#endif
:Now the remaining preprocessor directive defines
ADD_H
and we're left with the final translation unit:Now this file can be compiled. If you call a function like
add
, the compiler only needs to be able to see the declaration of that function for it to compile successfully. It is expected that the function will be defined in some other translation unit.So now let's look at preprocessing
add.cpp
. In fact,add.cpp
doesn't have any preprocessing directives, so nothing needs to happen. Typically, you would#include "add.h"
, but your program will still compile if you don't. So after preprocessing we still have:This then gets compiled and we now have a definition of the
add
function.After all
.cpp
files have been compiled, they are then linked. The linker is responsible for seeing that the compiledmain.cpp
uses the functionadd
and so looks for its definition. It finds the definition in the compiledadd.cpp
and links them together.You may then wonder why we have include guards at all. It seemed to be pretty worthless in this example. That's right, in this example it didn't really have any use. Include guards are there to prevent the same header being included twice in a single file. This can easily happen when you have a more complex project structure. However, let's look at an unrealistic example where
main.cpp
includesadd.h
twice:Preprocessing this gives you:
The first
#ifndef
will be process, it will see thatADD_H
is not yet defined, and everything up until the#endif
will remain. This then definesADD_H
.Then the second
#ifndef
is processed, but at this pointADD_H
has been defined, so everything up until the#endif
will be discarded.This is very important because having multiple definitions of a function (and many other things) will give you an error.
The IDE compiles each .cpp file in turn to generate an object file (the machine code) for that particular file.
With all this done it writes the bits up to form an executable. the IDE knows what needs to be linked with what.
This is a bit simplistic anwser