First of all, if we want to have a runnable program, we need to go through two steps. The first step is to compile the C + + file into obj, the second part is to link the obj file into a translation unit, and finally we get the executable program;
First, compile;
The first step of compiling is to scan the preprocessing statements [#include, #define, #if... Etc.] in C + + files;
Let's talk about #include here. In fact, the work of #include is very simple, that is, paste and copy the contents of the specified C + + file to the specified location. Let's take an example:
#include<iostream> int main(){ std::cout<<"Hello Wrold";
Obviously, this program will report an error because a semicolon is missing;
Then we open a file called endbrace. There is only one semicolon in it:
}//Endbrace.cpp
Then we #include"Endbrace" where we need}, so we have:
#include<iostream> int main(){ std::cout<<"Hello Wrold"; #include"Endbrace"
At this time, you will find that the compiler has passed, because the content in Endbrace has been changed to #include "Endbrace", which is equivalent to:
#include<iostream> int main(){ std::cout<<"Hello Wrold"; }
See if #include's work is very simple. If we #inlcude < iostream >, nothing particularly complicated will happen, just paste the contents of a file called iostream into the corresponding position;
Then let's talk about what translation unit is: note that translation unit and C + + file are two terms, which means that the two things are not equivalent, because if A file A declares A function not defined in A and the definition of the function is in B, the two files are regarded as A translation unit;
After preprocessing, the compiler translates it into mechanical language, and finally generates an obj file;
Then there is the link. What happens in the link?
Let's first clarify the sequence of events: first, translate each C++ file into an obj file, and then link each obj file into a translation unit;
To know what a link is, this dish thinks it's better to start with a link error:
Let's write one cpp file:
#include<iostream> int mul(int a, int b) { return a * b; } void show(const char * a) { std::cout << a; }
We click build [remember this noun], and then the system will report an error, because we don't write the program entry [generally, the program entry is the main function], which is normal, but if we CTRL+F7, we don't report an error. Why? Because CTRL is a compilation instruction, it will When cpp files are compiled into obj files, there is no requirement for the files to have a program entry [this is well understood, because sometimes multiple files need to be compiled, and it is impossible for all files to have a main function], so we can know that finding the program entry is a part of the link;
Then we add the main function:
#include<iostream> int mul(int a, int b) { return a * b; } void show(const char * a) { std::cout << a; } int main(){ }
The program can pass, so let's look at another error:
#include<iostream> int mul(int a, int b) { return a * b; } int main(){ show("Hellow world"); }
We are in another The show function is written in the cpp file. Let's call it show cpp:
#include<iostream> void show(const char * a) { std::cout << a; }
Run and report error:
This is because although I have the show function, the source cpp [main function file] doesn't know that this function exists. Even if the show function is next door, we have to let the source cpp remembers this function and finds it in other files;
This is actually easy to do. We can directly declare this function at the beginning:
#include<iostream> void show(const char *); int mul(int a, int b) { return a * b; } int main() { show("Hellow World"); }
show. If CPP remains unchanged, it can run successfully at this time;
So we know that finding function declarations is also part of the link [function definitions in other files]
But if we change show Functions in CPP:
#include<iostream> int show(const char * a) { std::cout << a; return 0; }
This will also report an error because of the source The function feature of the show function in cpp is marked show The function characteristics of the show function in cpp are different, so they cannot be matched;
Here's another error:
We will show Show function recovery in CPP:
#include<iostream> void show(const char * a) { std::cout << a; }
Then, we copy the show function into two copies:
#include<iostream> void show(const char * a) { std::cout << a; } void show(const char * a) { std::cout << a; }
At this time, the linker will not be happy, because there are two same functions, and the linker will not know which to link, but if you click build, a compilation error will appear:
This is because this situation is not allowed in the compilation step. An error is reported before the link is reached, which also shows that the compilation occurs before the link.
If we go directly to the source cpp implements the show function, and show cpp recovery, then a link error will occur:
#include<iostream> void show(const char * a) { std::cout << a; }
#include<iostream> void show(const char *); void show(const char * a) { std::cout << a; } int mul(int a, int b) { return a * b; } int main() { show("Hellow World"); }
This is because you just look at everyone cpp files can be compiled [because the compilation only considers whether a single file is legal], and then when linking, because of the source The declaration in cpp will be linked to show cpp's show function, and the source There is a show as like as two peas in cpp, so this happens.
This error is more likely to be triggered when:
We define a head H header file, which stores the show function, and the show function in the show function should be the Initshow function. The contents of each file are as follows:
head.h:
#pragma once void show(const char * a) { std::cout << a; }
show.cpp:
#include"head.h" void Initshow() { show("Initshow"); }
Source cpp:
#include<iostream> #include"head.h" int main() { show("Hellow World"); }
If you don't believe it, the system will report an error:
Remember what #include preprocessing statements do? Yes, it will put the head Copy and paste the content into h.show cpp and source In cpp, when the linker links three files at this time, the show function is defined twice, so an error is reported;
How can we solve this situation here?
We have two methods. The first is to put head The scope of the show function in CPP is limited to this file. Use the static keyword:
#pragma once static void show(const char * a) { std::cout << a; }
Then define the show function as an inline function:
#pragma once inline void show(const char * a) { std::cout << a; }
What principle is this?
The implementation is the static keyword, which specifies that a function only works in this file and cannot be called by other files [note here that because it is #include pasted and copied, there is a static show function in both the source. CPP and show.cpp], because it only works in this file, it will not conflict with functions with the same function characteristics in other files, so this problem can be solved;
Then define the function as an inline function:
The solution of inline function is actually more violent, that is, where the inline function is called, the calling statement is replaced with the function content [Note: it is the function content, not the function definition;], Because it is the function content, not the function definition, let alone the function conflict;
If the inline function is not recommended by the system, the system will automatically determine whether the inline function is suitable for the inline function;
To sum up:
Step 1 compilation: translate each file into obj file. The step is to first process the preprocessing statement and then compile it into mechanical code. Its feature is to treat each file independently. The compilation of one file will not affect the compilation of another file;
Step 2 link: link each file into a translation unit, which is vulnerable to interference, especially various redefinitions, which can be repaired by static statement and inline statement;