1. 程式人生 > >C ++標頭檔案的十大錯誤,如何解決這些問題

C ++標頭檔案的十大錯誤,如何解決這些問題

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow

也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!

               

Top 10 C++ header file mistakes and how to fix them


C++ header files is a rather mundane topic by most standards. Talking about header files is not as interesting as discussing complex search algorithms or debating design patterns . It’s not an academically stimulating subject to teach, so most CS programs do not emphasize header file design in their courses.

However, not having the correct header file design decisions can have significant ramifications on your project in terms of increases build times, compilation fiascos, code maintainability issues and plain information leakage. The larges your C++ project is, the more important this becomes.

Here’s a short description of the top 10 header file issues that can crop up if you’re not careful and how to avoid them.

C ++標頭檔案是大多數標準相當平凡的話題。說到標頭檔案是不是在討論複雜的搜尋演算法或辯論的設計模式一樣有趣。這不是一個學術課題刺激教,所以大部分CS程式不強調標頭檔案在設計自己的課程。
但是,沒有正確的標頭檔案中的設計決策會對您的專案顯著後果在增加方面構建時間,編譯慘敗,程式碼的可維護性問題和平原資訊洩露。在拉爾您的C ++專案,更重要的這成為。
下面是如果你不小心,以及如何避免它們能突然出現在排名前10位的標頭檔案問題的簡短說明。
http://blog.csdn.net/sergeycao/article/details/52537865

Mistake # 1: Not using “include guards” in a header file. 錯誤#1:不使用“包控制”在標頭檔案。

When the preprocessor sees a #include, it replaces the #include with the contents of the specified header. Using a include guard , you can prevent a header file being included multiple times during the compilation process. The most common way to define an include guard is as follows:

當前處理器會看到一個的#include,它用指定的頭的內容的#include。使用包括後衛,可以防止一個頭檔案在編譯過程中被包含多次。以限定包括防護裝置的最常見的方式是如下:

//File: Aircraft.h#ifndef AIRCRAFT_H#define AIRCRAFT_H \\the entire file #endif

You usually name your #include guard the same as the name of your header file.

There are two main problems that #include guards help solve.

1. It can help prevent danger circular references between header files which can cause weird compilation failures.

Consider the following example where main.cpp includes both Airbus.h and Boeing.h:

你通常命名include防範與您的標頭檔案的名稱。
有跡象表明,#包括警衛幫助解決兩個主要問題。
1.它可以幫助防止標頭檔案這可能會導致奇怪的編譯錯誤的危險迴圈引用。
看看下面的例子,其中的main.cpp包括Airbus.h和Boeing.h:

//File: Airbus.h#include "Boeing.h"namespace Airbus{ class Carrier {  Carrier();  ~Carrier(); };} //File: Boeing.h#include "Airbus.h"namespace Boeing{ class Carrier {  Carrier();  ~Carrier(); };} // main.cpp : Defines the entry point for the console application.#include "stdafx.h"#include "Boeing.h"#include "Airbus.h" int main(){    return 0;}

Compiling the code above gives the following error:

1>c:\users\user\documents\visual studio 2015\projects\smartpointers\headerfiles\airbus.h(2): fatal error C1014: too many include files: depth = 1024

If you’re in a large project with hundreds of include files, it might take some digging to find it out. If you’re using VS2015, you’re in luck because there’s an option to show the include order : Right Click the Project -> Properties -> C/C++ -> Advanced -> Show Includes. If you turn this on, you’ll see the following in the output window:

如果你在一個大的專案是數以百計的包含檔案,它可能需要一些挖掘找到它。如果你使用VS2015,你很幸運,因為有顯示包括訂單的選項:右鍵單擊專案 - >屬性 - > C / C ++ - >高階 - >顯示包括。如果開啟這個選項,你會看到在輸出視窗中以下內容:

Circular includes

Looking at this you can easily tell that there’s a circular reference between Boeing.h and Airbus.h. Fortunately, include guards can help fix the problem. The revised piece of code is below.

看著這個你可以很容易地告訴大家,有Boeing.h和Airbus.h之間的迴圈引用。幸運的是,包括守衛可以幫助解決這個問題。程式碼修改後的一段如下。

//File: Airbus.h#ifndef AIRBUS_H#define AIRBUS_H #include "Boeing.h" namespace Airbus{ class Carrier {  Carrier();  ~Carrier(); };}#endif //File: Boeing.h#ifndef BOEING_H#define BOEING_H #include "Airbus.h"namespace Boeing{ class Carrier {  Carrier();  ~Carrier(); };}#endif // main.cpp : Defines the entry point for the console application.// #include "stdafx.h"#include "Boeing.h"#include "Airbus.h" int main(){    return 0; }

2. In the absence of an include guard, a file will need to be processed multiple times and can cause significant build delays in large systems.

2.在沒有包括護罩,一個檔案將需要多次處理,並可能導致在大型系統顯著生成延遲。

Recommendation: Always use an include guard as shown above to optimize build times and avoid weird build errors. If your compiler supports and optimized #pragma once as an include guard mechanism, you should use that because it is usually more performant and less error prone than using an explicit include guard. For example, a lot of our internal code uses the following convention for public header files. Notice that if we're on a MS compiler where _MSC_VER is defined, we'll use the #pragma directive which is supported and optimized by the compiler.

建議:請始終使用如上圖所示,優化生成時間,避免怪異的生成錯誤的包括後衛。如果你的編譯器支援和優化的#pragma一次作為一個include防範機制,你應該使用,因為它通常是更好的效能和更小的誤差比使用顯式俯臥包括後衛。例如,很多我們的內部程式碼使用公共標頭檔案下列約定。請注意,如果我們在哪裡_MSC_VER定義一個MS的編譯器,我們將使用它支援和編譯器優化#pragma指令。

#ifndef HEADER_FILE#define HEADER_FILE #ifdef _MSC_VER#pragma once#endif  // _MSC_VER // Contents of the header file here #endif  // HEADER_FILE
http://blog.csdn.net/sergeycao/article/details/52537865

MISTAKE # 2: Incorporating "using namespace" statements at top level in a header file

錯誤#2:在標頭檔案頂層納入“使用名稱空間”語句

Headers should define only the names that are part of the interface, not names used in its own implementation. However, a using directive at top level in a header file injects names into every file that includes the header.

This can cause multiple issues:

  1. It is not possible for a consumer of your header file to undo the namespace include – thus they are forced to live with your namespace using decision, which is undesirable.
  2. It dramatically increases the chance of naming collissions that namespaces were meant to solve in the first place.
  3. It is possible that a working version of the program will fail to compile when a new version of the library is introduced. This happens if the new version introduces a name that conflicts with a name that the application is using from another library.
  4. The “using namespace” part of the code takes effect from the point where it appears in the code that included your header, meaning that any code appearing before that might get treated differently from any code appearing after that point.
頭應該定義只有那些介面,在它自己的實現不使用名稱的一部分的名字。然而,使用指令在標頭檔案中頂級的名字注入到每個包含標頭檔案。
這可能會導致多種問題:
這是不可能的標頭檔案的消費者撤消名稱空間包含 - 因此,他們被迫生活與你的空間使用的決定,這是不可取的。
這大大增加了命名名稱空間註定擺在首位,以解決衝突的機會。
可能的是該程式的工作版本將失敗時被引入該庫的新版本進行編譯。如果發生這種情況,新版本引入了與該應用程式是從另一個庫使用名稱相沖突的名字。
程式碼中的“使用名稱空間”的一部分生效了點地方出現,包括你的頭,這意味著在此之前出現的任何程式碼可能會被從該點後出現的任何程式碼區別對待的程式碼。

Recommendations:

1. Try to avoid putting any using namespace declarations in your header files. If you absolutely need some namespace objects to get your headers to compile, please use the fully qualified names (Eg. std::cout , std::string )in the header files.

1.儘量避免將任何使用空間宣告在你的標頭檔案。如果你絕對需要一些空間物品,讓您的頭編譯,請在標頭檔案中使用完全合格的名稱(如:性病::法院,性病::字串)。

//File:MyHeader.h:class MyClass{   private:    Microsoft::WRL::ComPtr<iunknown> _parent;    Microsoft::WRL::ComPtr<iunknown> _child;}</iunknown></iunknown>

2. If recommendation #1 above causes too much code clutter – restrict your “using namespace” usage to within the class or namespace defined in the header file. Another option is using scoped aliases in your header files as shown below.

2.如果建議1以上引起太多的程式碼混亂 - 限制你的“使用名稱空間”的使用在標頭檔案中定義的類或名稱空間內。如下圖所示另一種選擇是在標頭檔案中使用範圍的別名。

//File:MyHeader.h: class MyClass{namespace wrl = Microsoft::WRL; // note the aliasing here !private:    wrl::ComPtr<iunknown> _parent;    wrl::ComPtr<iunknown> _child;}</iunknown></iunknown>
http://blog.csdn.ne

給我老師的人工智慧教程打call!http://blog.csdn.net/jiangjunshow

這裡寫圖片描述