1. Background
A good programming specification and style is a sign of a program ape maturity. Standard coding can reduce code redundancy, reduce error probability, facilitate code management and code communication, etc., in fact, its role is much more than these, we have to keep in mind coding norms in mind.
Most of Google's projects use C + + to open survival. As every C + + programmer knows, C + + has a vigilance of astonished features, but it's complicated by the return of a powerful and complex, which makes code more prone to bugs, difficult to read and maintain.
The purpose of this guide is to explain how to 迕 line C + + code to circumvent its complexity, so that the code in the effective use of C + + astonished features, while 迓 easy to manage. One way to make your code easy to manage is to enhance code consistency so that others can understand that your code is vigilance important, and maintaining a unified programming style means that you can easily infer the meaning of various symbols based on the pattern matching rule. Creating generic, required habits with astonished and patterns makes the code easier to understand, and it may be a good choice to change some programming style under some 冴, but we 迓 should follow the principle of consistency and try not to return to it.
Another idea of the Google C + + Programming Guide is that the C + + feature is bloated. C + + is a huge language that contains a large number of advanced features, and in some cases we restrict or even prohibit the use of certain features to simplify code and avoid problems that may result.
Note : Google C + + Programming Guide is not a C + + tutorial, the reader needs to have good basic and programming experience for C + +. 2. Related specification of header file
The header file is a component of the compiled unit source file in a C + + project and is an integral part of a large project, and we must face it.
When using header files, we should observe the following specifications:
(1) Prevent the header file from being included in the source file multiple times;
(2) Minimizing the interdependence of the header documents;
(3) Reasonable header file contains order and name. 2.1 Prevent header files from being included in the source file multiple times 2.1.2 Conditional macro Protection
All header files should use the Conditional macro #ifndef #define #endif防止头文件被多重包含 (multiple inclusion), and the name format is:<project>_<path>_<file> _h.
To ensure uniqueness, header files are named based on the full path of the source code tree of their project. For example, the header file Foo/src/bar/baz.h in Project Foo is protected as follows:
#ifndef foo_bar_baz_h
#define FOO_BAR_BAZ_H ...
#endif//Foo_bar_baz_h
2.1.2 #pragma once protection
#pragma once is the compiler instructions, placed at the beginning of the header file, you can achieve the same effect as the condition macro, that is, the head file is repeated included only compile once, the face of the compile-time redefinition of the error.
Examples of usage are as follows:
Test.h
#pragma once ...
Test.cpp
#include "test.h" //Line 1
#include "test.h" //Line 2
2.2 Minimizing the reliance on header files
It is believed that many of the apes have suffered from the reliance of the head files. When porting a header file from another project to your own project, if you want to compile it, you find that the header file requires another header file, and another header file is needed ... that's a headache. This is the inconvenience caused by the dependency of the header file. 2.2.1 Front statement (forward declarations)
Use the predecessor Declaration (forward declarations) to minimize the number of #include in the header file, which means that you can rely on the declaration without relying on the definition.
Using a predecessor statement can significantly reduce the number of header files that require a bundle of tons. For example: The header file uses the class file, but does not need to access the file declaration, then the just in the header file requires the front declaration class file; #include "file/base/file.h" is not required.
In the header file how to use class Foo without having to access the definition of the class.
(1) Declare the data member type as Foo * or foo &;
(2) The function of the parameter, the return value type of Foo, only provides the declaration, does not define the implementation;
(3) A static data member type can be declared as Foo, because the definition of a static data member is outside the class definition. 2.2.2 Cheshire Cat Technology
Reduction of header file not only this method, which can use the Cheshire Cat technique (Cheshire cat Idiom), also known as PIMPL (pointer to implementation), Opaque pointer, and so on, is an interface defined in the class. The idiomatic method of encapsulating private data members in another implementation class. This method is mainly to hide the class data and reduce the header file dependency, and improve the compiling speed.
The Cheshire Cat (Cheshire Cat) is a fictional character in the fairy tale "Alice in Wonderland" (Alice's Adventure in Wonderland), created by British writer Carroll Lewis carroll,1832-1898. The image is a grinning cat with the ability to appear or disappear out of thin air, and even after it disappears, its smile hangs in midair. The Cheshire Cat's ability is consistent with Pimpl's function, that is, while data members "disappear" (hidden), our "Cheshire Cat" smiles can still be powerful.
For example, using Pimpl can help us save time in compiling programs. Consider the following class:
A.h
#include "BigClass.h"
#include "Verybigclass"
class a{
//...
Private:
bigclass big;
Verybigclass verybig;
};
We know that there are header files (. h) and implementation files (. cpp) in C + +, and once the header file changes, no matter how small the changes are, all files referencing it must be recompiled. For a large project, C + + compilation may consume a lot of time, if the code needs frequent changes, it is really unbearable. Here if we put bigclass big; and Verybigclass Verybig; By encapsulating the Pimpl into an implementation class, you can reduce the compilation dependency of A.h and reduce the effect of compile time:
A.h
class a{public
:
//The same interface as the original
private:
struct aimp;
Aimp *pimpl;
};
In addition to the above two methods, the use of interface classes can also achieve the goal of reducing the header file dependency, can only rely on oral files, because the interface class is only pure virtual function of the abstract class, no data member [3] ^{[3]}. 2.2.3 Unavoidable header file dependencies
If your class is a subclass of Foo, you must include a header file for it.
Sometimes it makes more sense to use the pointer member (pointer members, if the smart pointer is better) instead of an object member (the object members). However, the practice of returning samples reduces code readability and execution efficiency. If you don't want to include a header file for less than just one, don't replace it. 2.3 Reasonable header file contains order and name 2.3.1 contains header file name
The project header file should be arranged according to the project source code 彔 tree structure to avoid using UNIX file paths. (current directory) and. (parent directory). For example, Google-awesome-project/src/base/logging.h should be included as a return sample:
#include "Base/logging.h"
Here at compile time, you need to use compiler's compile option-I to specify the relative path or absolute path of the project versus the compiler working directory. That is, use-ISRC to indicate the search directory relative to the compiler working directory when compiling using g++.
Another need to know is that when using the include include header file, the relative directory is the working directory of the compiler when using relative paths.
For a search header file path, the compiler search order is as follows:
(1) Include custom header files, such as #include "headfile.h"
The search order is:
① first search the directory where the source files are located
② then search for the directory I specified
③ Search g++ environment variable Cplus_include_path (GCC is using c_include_path)
④ last search g++ 's default directory
/usr/include
/usr/local/include
/usr/lib/gcc/x86_64-redhat-linux/4.1.1/include
When each directory has the same file, find which one to use first.
(2) Include system header files or standard library header files, such as #include ① Search first-i-specified directory
② then searches the g++ environment variable Cplus_include_path
③ last search g++ 's default directory
/usr/include
/usr/local/include
/usr/lib/gcc/x86_64-redhat-linux/4.1.1/include
As with the above, each directory has the same file, find which one to use first. Note that #include <> does not search the directory where the source files are located.
Here to say include the default directory, it is not specified by the $PATH environment variable, but by the g++ configuration prefix specified (know that it can be specified when installing g++, do not know how to modify after installation, may be to modify the configuration file, need to study under). Prefix can be viewed in the following ways:
dablelv@tencent$ g++
-v Using built-in specs.
Target:x86_64-redhat-linux
configured with:. /configure--prefix=/usr--mandir=/usr/share/man--infodir=/usr/share/info--enable-shared--enable-threads=posix-- Enable-checking=release--with-system-zlib--enable-__cxa_atexit--disable-libunwind-exceptions-- Enable-libgcj-multifile--enable-languages=c,c++,objc,obj-c++,java,fortran,ada--ENABLE-JAVA-AWT=GTK-- Disable-dssi--enable-plugin--with-java-home=/usr/lib/jvm/java-1.4.2-gcj-1.4.2.0/jre--with-cpu=generic--host= X86_64-redhat-linux
Thread model:posix
gcc version 4.1.2 20080704 (Red Hat 4.1.2-46)
When the g++ is installed, the prefix is specified, and the default search directory is:
Prefix/include
Prefix/local/include
Prefix/lib/gcc/–host/–version/include
The default directory search header file can be masked by the-nostdinc++ option at compile time. 2.3.2 include header files in order
For more information, please refer to my other blog Google C + + programming style Guide header file containing order.
Here is a brief explanation of the order in which the header files recommended by Google C + + are included.
If Dir/foo.cpp is the source file in the project, the corresponding header file is Include/foo.h function, Foo.cpp contains header files in the following order:
Dir2/foo2.h (priority)
system call header file
C System file
+ + System file
Other library header file
in this project
This sort of sorting method effectively reduces the hidden dependencies, and we want each header file to be compiled independently. The simplest way to implement this is to include it as the first. h file in the corresponding. cpp. The same head 彔 the 挄 alphabetical order of the head file is the wrong choice. 3. Summary
(1) Avoiding multiple inclusions is the most basic requirement in programming;
(2) The predecessor statement is to reduce the compiler dependency, to prevent the modification of a header file to survival the Suwa effect of multiple meters;
(3) The name of the containing header file is used. Although convenient but easy to confuse, the use of a more complete project path seems clear and organized;
(4) The order of the included files in addition to aesthetics, the most important thing is to reduce the hidden dependencies, so that each header file in the "Most need to compile" (corresponding to the source file) of the place compiled, some people put forward the library file in the end, the return-like error is first in the project file, the header files are placed in the corresponding source file in The return is sufficient to ensure that internal errors are found in time. Reference Documents
[1] Google C + + Programming style Guide header file inclusion order
[2] Baidu Library. Google C + + code specification Chinese version
[3] C + + interface classes
[4]linux System compiles C + + program header file and library file search path