I. Preprocessor - Compiler - Assembler - Linger Preprocessor processes the relevant preprocessing instructions, generally instructions beginning with "#". Such as: #include "xx.h" #define et al. The compiler translated the corresponding * .cpp into * .s file (assembly language). The assembler handles * .s generated the corresponding * .o file (OBJ target file) Last linker links all * .o files into an executable file (? .Exe) 1. Part: First, I want to know the components (can Temporarily and narrowly understood as a class) Generally divided into header file (I like to be called interface, such as: *. H) and implement files (such as: *. CPP). The general header file will be placed some Dong Dong as an interface as an interface. The implementation file is mainly implemented by the specific code. 2. Compile a single file: Remember that IDE compiles only the implementation file (such as * .cpp) to generate OBJ when the Bulid file is generated. You can compile it to a certain? .Cpp Press CTRL F7 to generate the corresponding one? .Obj file. When compiling? .Cpp, the IDE will handle the header file included in the order in. CPP (if there is a file in the header file, it will follow the process of processing the individual files in order. .) 3. Internal links and external links: Internal, external links are the foundative stuff, but it is also the easiest place to be wrong, so it is necessary to discuss this here. The sign generated by the internal link is only in local? .Obj, and the external link is visible between all * .Obj. Such as: Inline is the internal link, and the variables directly declared in the file header are external links without inline. The function (without a function body) in the file header is an external link, and the belt correspondence is generally internal link (because the IDE will try to use it as an inline function) What is the role of internal links and external links ? The following uses VC6 to give an example: // file main.cpp content: void main () {} // file T1.cpp content: #include "ah" void test1 () {foo ();} // file t2.cpp Content: #include "ah" void test2 () {foo ();} // file ah content: void foo () {} is good, generate an empty console program with VC (File - New - Projects - Win32 Console Application) And turn off the pre-compiled option switch (Project - setting - CagegoryRecompiled Headers - Not Using Precompiled Headers) Now you open T1.cpp Press Ctrl F7 Compilation Generation T1.Obj Press Ctrl F7 to build T2.Obj by opening T2.cpp By passing when you link: lineing ... t2.obj: error lnk2005: "VOID __CDECL FOO (VOID)" (? Foo @@ yaxxz) already defined in t1.obj This is because: 1. Compile T1. The FOO function prototype definition that the CPP asks when the FOO in #include "ah" is external link, so the FOO symbol is recorded in T1.Obj is external. 2. Compiling T2.CPP The foo function prototype definition when it is processed to the FOO in #include "a.h" is external link, so the FOO symbol is recorded outside in t2.obj. 3. Finally, when link T1.Obj and T2.Obj, VC found that there are two places (T1.Obj and T2.obj) define the same external symbol (note: is defined, external symbols can be declared, but not Many definitions, because the external symbol is globally visible, assuming that there is a T3.cpp declaration that this symbol is used to call T1.Obj or t2.obj in t2.obj, so it will be reported. There are several ways to solve: a. Rewriting the definition in A.H as a declaration, and use another file a.cpp to store the correspondence.
(Tip: Try the above program) (the function body is placed in any of the other CPPs, such as t1.cpp, but good habits are to store corresponding CPP files). At this time, the file including AH has a function body code in A.Obj, and other OBJ files that include AH's CPP generates only corresponding symbols without a function body, such as T1.Obj, t2.obj, only symbols, when final When the link, the IDE will link the A.Obj's Foo () function to the EXE file and convert the FOO symbol in the T1.Obj, T2.Obj into the address in the function body EXE file. In addition: How to make it declare when the variable is placed in AH, how to make it a declaration? For example, we join: class cfoo}; cfoo * obj; at this time, press F7 to perform Build: Linking ... t2.obj: error lnk2005: "Class Cfoo * Obj" (? Obj @@ 3PAVCFOO @@ a) ALREADY Defined in T1.Obj A good way is to define this variable in A.CPP (Cfoo * Obj, Then copy this definition into the AH file and plus extern (extern cfoo * Obj can pass. Of course, Extern can also declare before any call to this variable, but strongly recommend nothing, because of everywhere EXTERN It will cause the interface to be uniform. Good habits are the interface generally placed the corresponding header file. B. Modify the definition in AH to internal links, add inline keyword, then each T1.Obj and T2. Obj is stored in a FOO function body, but they are not external symbols, so they will not be referenced by other obj files, so there is no conflict. (Tip: Try the above program) In addition, I made an experiment to verify "The VC is a logo of whether it is an external symbol in the OBJ file" (a bit winding). You can take a look, as follows: (1) File content: // file main.cpp content: void main () {} / / File t1.cpp content: #include "ah" void test1 () {foo ();} // file T2.cpp content: #include "ah" void test2 () {foo ();} // file AH content : Inline void foo () {} (2) Select T1.cpp Press Ctrl F7 to be compiled separately, and modify the compiled T1.Obj to t1.obj_inline (3) select T2.cpp Press Ctrl F7 to compile, and Modify the compiled T2.Obj to t2.obj_inline (4) delete files except T1.Obj_inline and T2.Obj_inline. (5) Modify AH content as: void foo () {}, make it Test (6) Rebuild All files. This time prompt: linking ... t2.obj: error lnk2005: "void __cdecl foo (void)" (? Foo @@ yaxxz) Already Defined in T1 .Objdebug / cl E.EXE: Fatal Error LNK1169: One or more Multiply Defined Symbols Found (7) Well, look at the newly generated OBJ file in the debug directory under the project directory.
Let's take a look at it, open Project - Setting - Link in the menu, copy all the content under Project Options, as follows: kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib OLIB OLIB OLIB OLIB OLIB OLI32 .lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib / NOLOGO / SUBSYSTEM: CONSOLOLO / INCREMENTAL: YES /PDB: "DEBUG/CLE.PDB" / debug / machine: i386 / @:"de.e.exe "/ pdbtype: sept modified it: link.exe kernel32. lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32 .lib shell32.lib ole32.lib oleaut32.lib uUid.lib odbc32.lib odbccp32.lib / NOLOGO / SUBSYSTEM: Console / Incremental: Yes /PDB :"debug/cle.pdb "/ debug / machine: i386 / out:" Debug / Cle.exe "/ PDBTYPE: sept debug / t1.obj debug / t2.obj debug / main.objpause Note how many link.exe in front, behind the debug / t1.obj debug / t2.obj debug / main. Obj and the last PAUSE batch command, then save it to the project directory (see the debug directory in this directory), you will see: t2.obj: error lnk2005: "void __cdecl foo Void) "(? foo @@ yaxxz) already defined in t1.objdebug / cle.exe: Fatal Error lnk1169: one or more multiply defined Symbols found is very good, we link the original OBJ file to get the effect of REBUILD in VC ALL is the same. Then now we override the backup T1.Obj_inline T1.Obj and t2.obj_inline override T2.Obj and manually link should not be wrong, because the original T1.Obj_inline and t2.obj_inline are stored in internal link symbols . It is good to run Link.bat, and don't expect it, the link is successful, look at the exe file in the Debug directory.
This illustrates the inner or external symbol in the OBJ has a logo logo! (Tip: Why not use the VC's F7Build link, because the file time changes, build will regenerate new Obj, so we use manual link to ensure that OBJ is unchanged) [Note BJ information available Dumpbin.exe View] 4. # include rule: There are many people don't know where the #include file should be put? 1). Enhance the integrity of the part: In order to ensure the complete components, the first #include of the component's CPP implementation file (such as Test.cpp) should be its own header file (such as Test.h). (Unless you use the pre-translated head file, the pre-compiled head must be placed first). This ensures that other interfaces (such as AH, etc.) must be placed in the file header (Test.h), not in the CPP (Test.cpp) The other header file (AH, etc.) is dependent on its own header file (Test.H, etc.) (because this forces other files (B.CPP) including this component (Test.h) must also Write again in including (ie B.CPP to #include "test.h" must also #include "ah") ". In addition, we generally try to reduce the dependencies between file headers, see below: 2). Reduce parts Dependencies: Between 1, try to put the #include to the file in the CPP. This requires us not to directly reference the implementation of other variables directly in the header file, but move this reference to implement the file. Middle. For example: // file foo.h: class cfoo {void foo () {}}; // file test.h: #include "foo.h" class ctest {cfoo * m_pfoo; public: ctest (): m_pfoo (NULL) {} void test () {if (m_pfoo) {m_pfoo-> foo ();}} ...........}; // file Test.cpp: #include "test.h "..... As mentioned above Test.h, we can actually move to Test.cpp files."