Chapter 4 basics-5th. c ++ project composition

Source: Internet
Author: User

[Back To Directory]

Vernacular C ++

 

5.3. c ++ project composition

First, we know that writing a C ++ program may require multiple source files, such as A. cpp and B. cpp.

Is it possible to use only one source file? It seems that we can. For example, there is only one main. cpp for the "Hello World" classic edition and other projects we have previously written.

In fact, even if it is a small program such as "Hello World", we have to pay the departure fee of the chainer comrade. Because we use STD: cout, STD: cout in the code from the C ++ standard library, while C ++ standard library, it is also possible to call the C standard library-"standard library" file, which is actually a "target file". Generally, it is a package of multiple "target files". The conclusion is, even if we write only one "Main. CPP, the compiler only compiles one "Main. o. O "and some necessary standard library files.

5.3.1. Project File

The project file is not necessary. You can directly use the G ++ compiler to write the command line to compile or link the C ++ source file, but we just mentioned that, the C ++ compiler compiles a single source file, which is inconvenient. Therefore, the project file is required.

In UNIX, the most popular C ++ project file is called "makefile/File Creation ". That is equivalent to "batch file processing" and does not require any IDE. In Windows, each ide usually has its own project file format. Code: blocks can use makefile, but the default and more convenient method is to use the code: blocks custom project file with the extension: ". (Code: blocks project ).

TIPS: Workspace: manage multiple projects

In addition to project files, code: blocks also provides "workspace Files" for managing multiple related projects at the same time. The extension is. workspace ".

 

5.3.2. source file and header file

As a general saying, we often refer to all the code files written by programmers as "source files". However, if the compiler is a single source file for compilation, the "source file" here is limited to the extension ". CPP "or". C ", or". cxx files, and HPP ",". h ",". files such as hxx are called "header files ".

The extension is used to differentiate the inverse. As we have just said, if a function is needed somewhere in the code, and the function has not been defined before the current position of the code, we can "declare" the function's length, to cheat the compiler (the linker will help us find the real location of the function); then, let's assume that we ". CPP "implements 100 functions, while in" B. CPP and C. CPP should be used in all. Does it mean that we have to write 200 "function declarations?

Of course, you don't need to go forward. We mentioned: "function declaration" is like a function business card, and "header file" is a name card folder containing multiple declarations, because, we can. the 100 function declarations in CPP are all written to a header file (usually called ". HPP "). In any source file that requires the relevant function, run the following command:" # include. HPP "imports all declarations.

Because the "header file" is not a compilation unit, we only need to let compilation find these headers, similar to libraries provided in the form of "header files" such as C ++ standard libraries; for other libraries that are directly extended in the form of "source files", if we want to use it in a project, we must provide the "source files ", it is best to copy one copy first, and then add the project file for compilation.

In the preparation section, we have installed many extension libraries. We noticed that almost all extension libraries provide an include sub-directory. Normally, the header files of the extension library exist under this directory (there may be sub-Directories. For example, the include directory of the MySQL ++ database is: e:/cpp_ex_libs/MySQL ++/3.0.6/include.

[Classroom assignment]: Find the MySQL header file

Go to the include directory in MySQL ++ and find the "MySQL ++. H" file.

 

Now, if we want to use the MySQL ++ library, we need to include a file named "MySQL ++". Is the source code written as follows?

# Include "E:/cpp_ex_libs/MySQL ++/3.0.6/include/MySQL ++. H"

It is not only difficult to use absolute paths, but also makes the source code very generic. If no absolute path is written, how can the compiler find the MySQL ++. h file?

It turns out that compilation allows us to specify parameters in the command line to tell it where to find a header file if it cannot be found. For G ++, this parameter is "-I header file path". The solution in this example is as follows:

G‑cmd.exe-I "E:/cpp_ex_libs/MySQL ++/3.0.6/include /"......

However, we do not directly write the command line, but call the compiler through code: blocks. Therefore, code :: blocks requires me to configure the path of the extension library required for this project in the project file. The specific configuration method will be discussed in the IDE chapter.

5.3.3. Use header files

Header files are like "business cards" or "card holders". They generally contain data declarations, function declarations, and Type Definitions (typical ones include struct/class. A person's business card can be distributed to many people. A header file is usually included in multiple source files. In addition, header files can also be included in each other, which leads to a bad possibility: the same header file is often repeatedly included in the same project.

  • Unique include

In our life, we don't like to have multiple duplicate business cards for the same person. For C ++, repeated inclusion of a header file not only reduces Compilation speed, but also leads to compilation errors: Data and function declaration can be repeated, but a type cannot be repeatedly defined.

# Define can define a "macro symbol" and use # ifndef to determine whether a "symbol" has been defined:

# Define ABCD // defines a macro Symbol: ABCD # ifdef ABCD // determines whether ABCD is "defined"/* The code here will only be compiled if ABCD has a definition, otherwise, it is skipped */# endif

In this example, the # ifdef indicator is the opposite. # The letter 'N' in ifndef is not, which is used to determine whether the specified symbol is "undefined ". We can use the following methods to ensure that a header file is actually included only once. Assume that the current header file is named "my_header.h"

001 # ifndef _ my_header_h_002 # DEFINE _ my_header_h_003 // the content to be declared or defined is put here XXX # endif // _ my_header_h _

Assume that this is the first time that a project contains the file "my_eader.h:

When the Pre-compiler processes "myheader. H", it first runs into the following pre-processing command (usually the first line ):

# Ifndef _ my_header_h _

It determines whether the macro symbol "_ my_header_h _" is "undefined". Because this is the first time this file is included, it has not been defined yet, so line 002 immediately defines this symbol. Then there is the actual content of this header file (from row 003 to the first line before XXX ).

Next, let's assume that a Code contains this header file again, but this time the pre-compiler finds that the symbol _ my_header_h _ has already been defined, after it jumps directly to line XXX (# endif.

The trick is: we should take a unique macro symbol for each file, which is also known as the "Protection character ". To enable each header file to be "hang" a unique protection character, you can map the name of this symbol to the header file name. It is customary to change all letters to uppercase letters, put '. 'Change to '_'. If you want to be cool, you can add an underscore to the front and back.

[Tips]: What should I do with header files with the same name?

Sometimes, the two header files in different directories may have the same name. In this case, we need to use a longer protection character name.

 

  • Use custom header files

# Include accepts two types of header file instructions

#include <library_header.h>   #include "my_header.h"

Generally, we use angle brackets (<>) for header files in the standard library, and use double quotation marks ("") for header files written by ourselves in the current project. For third-party libraries, if we have configured the Global Path in IDE, we can also use angle brackets, such as wxWidgets or boost libraries.

Code: blocks provides a convenient "file wizard" to generate header files or source files. However, this section describes how to add header files and source files manually.

First, create a console Project (named includemo1) in the Wizard. At first, it has only one file: Main. cpp.

Click "file"-> "new"-> "Blank file" (or the hot key: Ctrl + Shift + n) in the main menu. The following is the question box:

"Do you want to add the new file to the current project (you must save it before joining the project )?"

Select "yes" and save the file as "my_file.hpp ". Because a project has two Build targets by default: Debug and release, the IDE will then ask which build targets should be added to the new file. Select all targets.

Create a new file and save it as "my_file.cpp". Add the file to all targets. The project file tree is as follows:

Figure 5-4 Add the project tree after my_file.cpp/. HPP

Then, we will --

  • In my_file.hpp, define the mystruct class and declare the my_function function;
  • In my_file.cpp, implement the mystruct class and the my_function function;
  • In Main. cpp, use the mystruct class and my_function function.

 

Complete the following code separately. To help eliminate errors caused by incorrect input code, press Ctrl + F9 to compile each time the content of a file is completed, then proceed to the next step.

First,Code in my_file.hpp -- Declaration and definition:

# Ifndef _ my_file_hpp _ # DEFINE _ my_file_hpp _ // define a class struct mystruct {mystruct ();~ Mystruct () ;}; // declare a function: void my_function (INT year, int month, int day); # endif // my_file.hpp

Second,Code in my_file.cpp -- Implementation

# Include "my_file.hpp" // contains the custom header file # include <iostream> // contains the standard library file using namespace STD; mystruct: mystruct () {cout <"mystruct construct. "<Endl;} mystruct ::~ Mystruct () {cout <"mystruct destruct. "<Endl;} void my_function (INT year, int month, int Day) {cout <year <'-' <month <'-' <day <Endl ;}

Third,Code in Main. cpp -- Use

# Include <iostream> # include "my_file.hpp" // introduce mystruct and my_function using namespace STD; int main () {mystruct; my_function (1974, 4, 20 ); return 0 ;}

5.3.4. Library File

The C ++ extension library can be a common source file or a "library file" that has been compiled into the target file ". For the former, it is similar to the source file we write. You need to add the project to compile the source file. For the latter, you only need to join the link. There are two link modes: static Link Library and dynamic link library. We have already introduced the differences between the two in preparation.

  • Static Link Library

Complete the link during the "Build period" (often referred to as the "compilation period" in general. That is, after the source file is compiled, the library file and other intermediate files are linked together. Therefore, library files are also merged into executable files (programs ).

The file extension of the static Link Library, usually ". lib" or ". ".

  • Dynamic Link Library

The file extension of the dynamic link library, usually ". dll", ". So", and ". O ".

This class library uses a specific technology that allows the database and program to be merged in the memory only when the program is running. The main task completed by merging is "positioning ". For example, in the main program k.exe, you need to use a signature in the dynamic library M. DLL to be "Void foo(partial region. Naturally, k.exe needs to know that the" Foo () "function is" Address "in M. dll ". Because the program (including the dynamic library) needs to be loaded into the memory during runtime, this address is a "memory address ".

How to locate the address of a function (or other memory objects) in a dynamic library is as follows:

First,Automatic Import

For C ++ programming, when we write a complex program, the program is often divided into a main project (used to generate executable files) and some sub-projects (used to generate dynamic libraries ). At this time, the commonly used method is to automatically load the required dynamic library by the executable program at startup, and complete the addressing.

How does a program know which functions need to be loaded? How do I know the addresses of these functions? This requires the third type of Database: "Import/import library" (the full name of the symbol import library ). Import to database saves the offset addresses of all (to be exported) functions and other symbols in a dynamic library.

The offset address is not a "memory address". It is the address of each function in the DLL file. When the dynamic library is loaded to the memory, the entire dynamic library has a starting address. Function Memory Address = DLL start address + function offset address.

When compiling a dynamic library project, in addition to generating dynamic library files, we also generate "import to Database ". When we need to use this dynamic library in an execution file and want to use the "Automatic Import" method, we need to import the "Import to Database" in the "static link" mode, join the project. For G ++, importing data to the database usually uses ". A" as the extension.

C ++ has no unified standards for the Automatic Import of dynamic libraries. Therefore, this technology cannot be used between different compilers. For example, if a dynamic library compiled by Borland C ++ or visual C ++ is used, the executable files compiled by G ++ cannot be called automatically.

Second,Manual Import

Manual import of function and other data in the dynamic library is actually a standard of C language. C ++ is compatible with this function. To use this technology, a function or data must be exported according to the C language standard, which is usually called the "C Language Interface ". The C language interface is a fact standard when the operating system exposes its programming interface.

When the program is running, it loads the specified dynamic library to the memory through some specific statements only when necessary, then finds the required function, and calls this function. You can also detach the dynamic library from the memory after it is used up. This is the biggest feature of manual import of dynamic libraries.

 

It is time to take a look at the form and usage of the C ++ Library:

Figure 5-5 C ++ library format and usage

 

No matter what form is used, the "header file" is provided to prevent users from writing their own statements. This is the most basic requirement. For the C ++ standard library and many sub-libraries in boost, the "generic" technology is used, so the "pure header file" form is used.

Finally, we have never mentioned this, but it is very important to use the library: Library instructions. Generally, open-source libraries can be found on a common official website.

 

[Back To Directory]

Vernacular C ++
Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.