Recently in learning c++, I encountered some definition and declaration problems in the process of compiling and linking. After consulting information in many places, I basically solved my doubts. Now record with this, hope to let the person behind take some detours less.
C++
What extension should be used for the header file of?
The common formats in the industry are as follows:
implementation file
*.cpp
*.cc
*.cc
*.c
header file
*.hpp
*.h++
*.hh
*.hxx
*.h
In short: it is recommended to use.cpp for source files and.hpp for header files
There’s nothing to say about implementation file, it’s ok to use.cpp/.cc. But the header file needs attention.
H is considered to stand for header, so many people also like to use.h as a header extension in C ++. The extension does not affect the result of the compilation and is not important to the compiler (even with.txt). But in a large project where C and C ++ are mixed, you can’t immediately tell whether this is a CPP header file or a C header file; In addition, if you write CPP syntax in c file, it will tell you that it is not correct (of course it will still compile).
Therefore, I think the best result is that if any c++ syntax is involved in the header file, then the header file should end with.hpp, otherwise it should end with.h
implementation file
与 header file
What to write
In theory, you can implement file and header file, as long as it’s supported by c++, you can write whatever you want, like if you put the function body in the header file, We can compile this function as part of an object file as long as we include the header file in any implementation file (compilation is in implementation file units, If you don’t include this header file in any implementation file, this code is null, you can declare functions, variables, structs in the implementation file, that’s not a problem!!
So why does it have to be header file and implementation file? Why are functions, variables, macros, and structs declared in header files? Now in the implementation file we’re going to do the variable definition, what about the function implementation?
Here’s why:
-
If you implementa function body in a header file, and if you reference it in multiple implementation files, and compile multiple implementation files at the same time, Join the generated object file into an executable file. In every implementation file that references this header file, there is a code of this function. If this section of the function is not defined as a local function, then when joining, it will find multiple identical functions, and an error will be reported.
-
If you define a global variable in header file and assign the initial value to the global variable, then there are copies of the same variable name in multiple implementation files that reference the header file. The key is that the variable is assigned the initial value. So the compiler will put this variable in the DATA segment, and eventually at the join stage, there will be multiple identical variables in the DATA segment, and it won’t be able to unify those variables into a single variable, which means it will only allocate one space for that variable instead of multiple Spaces. Assuming no initial value is assigned to this variable in the header file, the compiler puts it in the BSS segment, and the linker allocates only one storage space for multiple variables of the same name in the BSS segment.
-
So if you declare macros and structs and functions and so on in the implementation file, then if you want to reference the corresponding macro and structure in another implementation file, you have to do the same thing again, If I change a declaration in one implementation file, and I forget to change a declaration in another implementation file, that’s a big problem, if I put all these public things in a header file, So if you want to use its implementation file you just need to refer to one!
-
Declare structures, functions, etc., in header files. When you need to wrap your code into a library and let others use your code, and you don’t want to release the source code, how can people use the functions in your library? ? One way is to publish the source code so that people can use it however they want, and the other way is to provide a header file where people can see your prototype function, so that people know how to call your function, just like you call printf, what are the arguments in it? How do you know that? Look at the related declaration in the header file!
How does a header file relate to a source file
Given that header file A.h declares a series of functions (only function prototypes, no function implementations) that are implemented in B.cpp, if I want to use the functions declared in A.H in C.CPp that are implemented in B.CPP, #include “a.h” is usually used in c.cpp, so how does c.cpp find the implementation in B.cpp?
The compiler preprocesses the #include command by copying the entire contents of a.h to #include “a.h”. This explains why many compilers don’t care what the file’s suffix is – because #include preprocessing does the job of copying and inserting code.
When the program is compiled, it does not look for the function implementation in the B.cpp file, only when link is used. When we use #include “a.h” in a B.cpp or c.cpP, we actually introduce declarations that make compilation work, and the program doesn’t care where or how the implementation is implemented. The source file is compiled to produce an OBJ file in which the functions and variables are treated as symbols. During link, you need to specify in the makefile which obj file you want to connect to (in this case, the.obj file generated by the B.cpp). In this case, the linker will look in the.obj file for functions implemented in the B.cpp. Build them into the executable file specified in the Makefile.
In Clion, you usually don’t need to write your own makefiles. You just need to include the required files in the project, and Clion will write the Makefiles for you automatically.
In general, the compiler looks for symbols in each.o or.obj file, not just one file or none at all. Therefore, if the same function is implemented in several different files, or the same global variable is defined, the link will prompt for redefined.
What is a statement? What is the definition?
- According to the CPP standard, a variable declaration must satisfy two conditions, otherwise it is a definition:
- Extern must be used;
- Cannot assign an initial value to a variable;
- A variable/function can be declared in multiple places, but can only be defined in one place;
It doesn’t matter if it’s defined or declared in header file or implementation file.
According to the above provisions, we can come to the following conclusion:
extern int a; / / declare
int a; / / define
int a = 0; / / define
extern int a = 0; / / define
Copy the code
Many programmers are confused about defining variables and declaring variables. The difference between defining variables and declaring variables lies in the definition of operations that will produce memory allocation, which is the concept of assembly stage. Declarations simply tell the module that contains them to look for external functions and variables from other modules during the connection phase.
How to use global variables/functions across files?
Variables/functions that we write in any file in the build module can be accessed in other files in the build module, but other files in the build module do not have access to this variable. So how do you share variables/functions across modules?
Extern is the correct extern. Keep this definition in mind when you do this: indicates that the variable or function you are modifying may reside in another module.
Keep the above definition in mind so that we can figure out the following questions
- Why in a world where
implementation file
To use an external variable in theextern
Declare the variable (or import the variable’s location)header file
)?- why
header file
Extern is used to declare a variable in extern?
The global variable
Extern = extern; extern = extern; extern = extern; extern = extern; extern = extern; extern = extern; extern = extern; Ld: Symbol (s) not found for architecture x86_64; ld: Symbol (s) not found for architecture x86_64;
Right way
- in
test1.hpp
In a statementextern int a;
- in
test1.cpp
Defined in theint a = 10;
(or useint a;
Definition, in which case the default value is 0.) - in
test2.cpp
中#include "test1.hpp"
, so that you cantest2.cpp
The a variable is used directly in.
Error Mode 1
Extern int a = 10 in header test1.hpp;
We already said that a variable can be declared in more than one place, but only in one place. In this case if we have more than one implementation file all #include “test1.hpp”, Ld: 1 Duplicate symbol for Architecture X86_64 (duplicate symbol for Architecture x86_64
Also, defining a variable in a header file is a very amateurish practice, so don’t rush to emulate it
Error Mode 2
Extern int a = 10 in header test1.hpp; , extern int a is used directly in test2. CPP; (No #include test1.hpp)
This avoids the problem of having multiple definitions, but it is not possible to use all other variables and methods defined by test1.hpp. Extern *** must be declared and then used.
conclusion
So we can come to the conclusion:
- Make declarations only in header files
The truth is always so simple!
Global function
Functions, like variables, are defined and declared. Extern is extern and extern is extern, but unlike a variable that must contain extern when declared, functions are defined and declared differently. Extern is extern and extern are extern and extern is not extern when declared. All other files know that the function is defined elsewhere. So extern doesn’t work.
So in CPP, adding extern before a function simply means that the function may be defined in another module; Or we can omit #include <***.hpp> when we use only one header.
static
use
whenstatic
Used to modify variables/functions in a class
Is a static member variable/function
- Memory is allocated when the class is loaded
- It can be accessed directly by the class name
whenstatic
Used to modify variables/functions outside of a class
Is a normal global static member variable/function
- Used to modify variables to indicate that they are stored in a global (static) area and not on the stack.
- Only valid for this compiled module (even if used externally
extern
Declaration does not work either), not really global (normal functions default toextern
) - Declaration and definition at the same time
- This can be used when local variables do not want to be released at the end of the function
static
For example, if you want to return an array and do not want the array function to be freed at the end, you can use static to decorate the local variable
Static makes variables visible only within the module. If two modules each have a value variable, do not treat static variables as the same memory. They are actually two parts of memory
Static is used for compiling modules.
- If a
implementation file
And all of#include ...
File is composed of a compilation module in more than onestatic int a = 0
, an error will be reportederror: redefinition of 'a'
- if
test.hpp
有static int a = 0
.test1.cpp
与test2.cpp
There are respectively#include "test.hpp"
, so this is one for each compiler modulestatic int a
CPP allows it to compile and run smoothly
const
Const is identical to static when used alone, and extern when used with extern
The use and significance of IFNDEF
#ifndef ensures that your header is compiled only once in this module.
Conclusion someThe header file
& The statement
& define
The rules of
header file
Is a declaration of the module’s interface, including the external functions and external global variables provided by the module for other module calls, for these variables and functions are required inheader file
As in theextern
Keyword declaration- Functions and global variables in the module must be in
implementation file
Beginning withstatic
Keyword declaration - Never in the world
header file
Define variables in - If you want to use variables and functions defined by other modules, directly
#include
其header file
Can.
If the project is large, there are many header files, and a few header files are often used, then
- Write all of these header files into one
header file
Go inside, say to preh.H- Write a
preh.cpp
“And there was only one sentence:#include "preh.h"
- for
preh.c
“In Project Settingcreate precompiled headers
For other c++ files, setuse precompiled header file
reference
- Extern and header file (*.h)
- How can a global variable be shared among multiple c++ files