I. C ++ compilation Mode
Generally, a C ++ program contains only two types of files:. cpp and. h. Where ,. the cpp file is called the C ++ source file, which contains the C ++ source code. the H file is called the C ++ header file, which contains the source code of C ++.
The C ++ language supports "separate compilation" (separate compilation ). That is to say, all the content of a program can be divided into different parts and placed in different. cpp files .. The items in the cpp file are relatively independent and do not need to communicate with other files during compilation and translation, you only need to compile the target file and then link it with other target files. For example, a global function "void a () {}" is defined in file a. cpp, which needs to be called in file B. cpp. Even so, file. cpp and file B. cpp does not need to know each other's existence. Instead, it can be compiled separately, compiled into the target file, and then linked, and the entire program can run.
How is this implemented? From the perspective of writing a program, it is very simple. In File B. cpp, declare the function "void a ();" before calling the "void a ()" function. This is because the compiler is compiling B. when cpp is used, a symbolic table is generated, and undefined symbols such as "void a ()" will be stored in this table. Then, the compiler searches for the definition of this symbol in other target files. Once found, the program can be successfully generated.
Note that two concepts are mentioned here. One is "Definition" and the other is "Declaration ". To put it simply, "Definition" refers to a complete description of a symbol: whether it is a variable or a function, what type is returned, what parameters are required, and so on. The "Declaration" only declares the existence of this symbol, that is, it tells the compiler that this symbol is defined in other files. I will first use it here, you can go to another place to find out what the link is. Define a symbol (variable or function) in the C ++ syntax. When declaring a symbol, you only need to write the prototype of the symbol. It should be noted that a symbol can be declared multiple times in the entire program, but must be defined only once. Imagine who should the compiler listen to if a symbol has two different definitions?
This mechanism brings many benefits to C ++ programmers and also introduces a programming method. Consider, if there is a very common function "Void F () {}", many of them are in the whole program. the CPP file will be called, so we only need to define this function in a file, and declare this function in other files. A function can be easily declared. However, if there are more functions, such as a lot of mathematical functions and hundreds of them, what should we do? Can Every programmer fully write down and write all functions accurately?
2. What is a header file?
Obviously, the answer is impossible. However, there is a simple way to help programmers Save the trouble of remembering so many function prototypes: we can write all the declaration statements of those hundreds of functions first and put them in one file, when programmers need them, they will copy them all into their source code.
This method is feasible, but it is too troublesome and clumsy. As a result, the header file can play its role. In fact, the content of the header file is the same as that in the. cpp file. It is the source code of C ++. However, the header file does not need to be compiled. We put all the function declarations in a header file. when CPP source files need them, they can be included in this file by using a macro command "# include. CPP file to merge their contents. in the CPP file. When the. cpp file is compiled, the. h file that is included will play a role.
For example, if there are only two mathematical functions: F1 and F2, we will put their definitions in math. cpp:
/* Math. cpp */
Double F1 ()
{
// Do something here ....
Return;
}
Double F2 (double)
{
// Do something here...
Return a *;
}
/* End of math. cpp */
And put the declaration of "these" functions in a header file math. h:
/* Math. H */
Double F1 ();
Double F2 (double );
/* End of math. H */
In another file main. cpp, to call these two functions, you only need to include the header file:
/* Main. cpp */
# Include "math. H"
Main ()
{
Int number1 = F1 ();
Int number2 = F2 (number1 );
}
/* End of Main. cpp */
This is a complete program. Note that. H files do not need to be written after the compiler command, but must be found in the compiler (for example, in a directory with main. cpp ). Both main. cpp and math. cpp can be compiled to generate main. O and math. O, and then link the two target files to run the program.
Iii. # include
# Include is a macro command from C language. It works before the compiler is compiled, that is, it works during pre-compilation. # The function of include is to include the content of the file written after it into the current file in an unaltered manner. It is worth mentioning that it does not have any other functions or sub-functions. Its function is to replace the content of the file written after it wherever it appears. Simple text replacement. Therefore, the first sentence (# include "math. h") in the main. cpp file will be replaced with the content of the math. h file before compilation. That is, when the compilation process is about to begin, the content of main. cpp has changed:
/*~ Main. cpp */
Double f1 ();
Double f2 (double );
Main ()
{
Int number1 = f1 ();
Int number2 = f2 (number1 );
}
/* End ~ Main. cpp */
Not many, just right. Similarly, we can see that, except for main. besides cpp, there are many others. if the cpp file also uses the f1 and f2 functions, they all need to write the # include "math. h.
4. What should I write in the header file?
Through the above discussion, we can understand that the role of header files is included by other. cpp files. They are not involved in compilation, but in fact their content is compiled in multiple. cpp files. By using the rule "only once defined", we can easily conclude that only variables and function declarations should be put in the header file, rather than their definitions. Because the content of a header file is actually introduced into multiple different. cpp files, and they will be compiled. It is okay to put the Declaration. if the definition is put, it is equivalent to the definition of a symbol (variable or function) in multiple files, even though these definitions are the same, however, this is not legal for the compiler.
Therefore, we should remember that, in the. h header file, only declarations of variables or functions can exist, rather than definitions. That is, you can only write sentences in the header file, such as extern int a; and void f. These are declarations. If you write a sentence such as int a; or void f () {}, the compiler will immediately report an error once the header file is contained by two or more. cpp files. (For extern, we have discussed earlier. Here we will not discuss the difference between definition and Declaration .)
However, this rule has three exceptions.
1. The definition of the const object can be written in the header file. Because the global const object does not have the extern declaration, it is only valid in the current file. Write such an object into the header file, even if it is contained in multiple other objects. in the cpp file, this object is only valid in the file that contains it. It is invisible to other files, so it will not lead to multiple definitions. At the same time, because the objects in these. cpp files are all contained in a header file, this ensures that the value of this const object in these. cpp files is the same, which can be two birds with one stone. Similarly, the definition of a static object can also be put into the header file.
2. the header file can be defined by an inline function (inline. Because the inline function requires the compiler to expand it inline according to its definition when it encounters it, instead of being a common function, you can declare it before linking it (inline functions are not linked). Therefore, the compiler needs to see the complete definition of inline functions during compilation. If an inline function can only be defined once like a common function, this is hard to do. Because it is okay in a file, I can write the definition of the inline function at the very beginning, so that the definition can be seen later. However, what if I still use this function in other files? This is almost no good solution, so C ++ stipulates that inline functions can be defined multiple times in the program, as long as inline functions are in one. the cpp file appears only once and. in the cpp file, this inline function has the same definition and can be compiled. Obviously, it is wise to put the inline function definition into a header file.
3. You can write the class definition in the header file. When creating a class object in a program, the compiler can know how to layout the class object only when the class definition is completely visible, the requirements for Class Definition are basically the same as those for inline functions. Therefore, it is a good practice to put the class definition into the header file and include this header file in the. cpp file of this class. It is worth mentioning that the class definition contains data members and function members. Data members are defined (space allocation) only when a specific object is created, but function members need to be defined at the beginning, this is what we usually call the implementation of classes. Generally, we put the class definition in the header file, and put the implementation code of function members in A. cpp file. This is acceptable and a good solution. However, there is another way. That is, the implementation code of function members is directly written into the class definition. In the C ++ class, if a function member is defined in the class definition body, the compiler will regard this function as inline. Therefore, it is legal to write the definition of function members into the class definition body and put them together in the header file. Note that it is invalid to write the definition of function members in the class definition header file but not in the class definition, because this function member is not inline at this time. Once the header file is contained by two or more. cpp files, this function member is redefined.
5. Protection Measures in header files
If the header file contains only the declaration statement, it will be okay if it is included in the same. cpp file multiple times-because the declaration statement is unrestricted. However, the three exceptions in the header file discussed above are also very useful for header files. Once a header file contains any of the above three exceptions and is contained multiple times by A. cpp file, the problem becomes serious. Although the syntax elements in these three exceptions can be defined in multiple source files, they can only appear once in one source file ". Imagine if. h contains the definition of Class A, B. h contains the definition of Class B. Because the definition of Class B depends on class A, B. H also # include. h. Now there is a source file that uses both Class A and Class B, so the programmer included both a. h and B. h In this source file. At this point, the problem arises: the definition of Class A appears twice in this source file! Therefore, the entire program cannot be compiled. You may think this is a programmer's mistake-he should know that B .h contains a.h-but in fact he should not know.
Using "# define" With Conditional compilation can solve this problem well. In a header file, use # define to define a name and use Conditional compilation # ifndef... # endif allows the compiler to determine whether the name is defined, and then decide whether to continue to compile subsequent content in the header. This method is simple, but you must remember to write it into the header file.