This is probably a stupid question, but I\'ve searched for quite a while now here and on the web and couldn\'t come up with a clear answer (did my due diligence goo
The header file declares functions/classes - i.e. tells the compiler when it is compiling a .cpp
file what functions/classes are available.
The .cpp
file defines those functions - i.e. the compiler compiles the code and therefore produces the actual machine code to perform those actions that are declared in the corresponding .hpp
file.
In your example, main.cpp
includes a .hpp
file. The preprocessor replaces the #include
with the contents of the .hpp
file. This file tells the compiler that the function myfunction
is defined elsewhere and it takes one parameter (an int
) and returns an int
.
So when you compile main.cpp
into object file (.o extension) it makes a note in that file that it requires the function myfunction
. When you compile myfunction.cpp
into an object file, the object file has a note in it that it has the definition for myfunction
.
Then when you come to linking the two object files together into an executable, the linker ties the ends up - i.e. main.o
uses myfunction
as defined in myfunction.o
.
I hope that helps
The preprocessor includes the content of the header files in to the cpp files (cpp files are called translation unit). When you compile the code, each translational unit separately is checked for semantic and syntactic errors. The presence of function definitions across translation units is not considered. .obj files are generated after compilation.
In the next step when the obj files are linked. the definition of functions (member functions for classes) that are used gets searched and linking happens. If the function is not found a linker error is thrown.
In your example, If the function was not defined in myfunction.cpp, compilation would still go on with no problem. An error would be reported in the linking step.
You have to understand that compilation is a 2-steps operations, from a user point of view.
During this step, your *.c files are individually compiled into separate object files. It means that when main.cpp is compiled, it doesn't know anything about your myfunction.cpp. The only thing that he knows is that you declare that a function with this signature : int myfunction( int x )
exists in an other object file.
Compiler will keep a reference of this call and include it directly in the object file. Object file will contain a "I have to call myfunction with an int and it will return to me with an int. It keeps an index of all extern calls in order to be able to link with other afterwards.
During this step, the linker will take a look at all those indexes of your object files and will try to solve dependencies within those files. If one is not there, you'll get the famous undefined symbol XXX
from it. He will then translate those references into real memory address in a result file : either a binary or a library.
And then, you can begin to ask how is this possible to do that with gigantic program like an Office Suite, which have tons of methods & objects ? Well, they use the shared library mechanism. You know them with your '.dll' and/or '.so' files you have on your Unix/Windows workstation. It allows to postpone solving of undefined symbol until the program is run.
It even allows to solve undefined symbol on demand, with dl* functions.
int myfunction(int);
is the function prototype. You declare function with it so that compiler knows that you are calling this function when you write myfunction(0);
.
And how do the header and main function even know the function definition exists?
Well, this is the job of Linker.
As suggested in Matthieu M.'s comment, it is the linker job to find the right "function" at the right place. Compilation steps are, roughly:
When you compile a program, the preprocessor adds source code of each header file to the file that included it. The compiler compiles EVERY .cpp
file. The result is a number of .obj
files.
After that comes the linker. Linker takes all .obj
files, starting from you main file, Whenever it finds a reference that has no definition (e.g. a variable, function or class) it tries to locate the respective definition in other .obj
files created at compile stage or supplied to linker at the beginning of linking stage.
Now to answer your question: each .cpp
file is compile into a .obj
file containing instructions in machine code. When you include a .hpp
file and use some function that's defined in another .cpp
file, at linking stage the linker looks for that function definition in the respective .obj
file. That's how it finds it.