更多C語言學習内容,請私信 我 “代碼” 獲取
在不得不清理一些不尋常的#include技術之後,我将就如何不使用#include以及如何使用它提出一些建議。
特定的代碼庫相對較舊,有其瑕疵和特點。換句話說,這是多年來在曆史上或歇斯底裡地發展的遺留代碼。
在一些枚舉和typedef之後,有問題的标題有很多包括 - 超過20個 ,在對源代碼進行一些分析之後,出現了以下圖片:該項目包含大約300個源文件和相應的頭文件,分布在少數目錄中。
project_root
utilities
| include
| | some_util.h
| | someother_util.h
| | ...
| some_util.cpp
| someother_util.cpp
| utilities.h
one_directory
| ...
another_directory
| ...
stdafx.h
main.cpp
請注意utilities.h标題 - 它是包含許多内容的标題。它包括一切在公用庫/ include目錄。其他目錄具有類似的結構,包括“主标題”,它将#include相應include目錄中的所有内容。還有utilities.h标題。
所有源文件基本上都是#include stdafx.h及其相應的目錄主标題。隻是偶爾,如果需要來自除實用程序之外的其他目錄的東西,它們也會#include該目錄的主标題。由于單個類頭隻是#included隻有一次,在主頭中,他們甚至不需要包含警衛。隻有主标題有一個#pragma once。
更多C語言學習内容,請私信 我 “代碼” 獲取
這有什麼問題?乍一看,這聽起來非常方便。如果我們在其中一個目錄中添加一個新類,隻需将标題#include到主标題中,我們就可以在目錄中的任何地方使用它。我們也可以在新類中使用該目錄中的所有内容,因為我們隻在其源代碼中包含了主标頭。
但是,這種技術會帶來許多問題。我不會進入(不一緻)使用單獨的“包含”目錄,因為這主要是品味和慣例的問題。#include "../../utilities/include/some_util.h清理時打字很多東西。
它很脆弱
想象一下,我們添加了一個新的類定義,它取決于主标題末尾的#included标頭。我們不能簡單地#include我們新類的标題中的其他标題,因為它沒有包含保護。它也會打破上述模式。相反,我們必須#include主标題中的新标題低于它所依賴的标題。
然後我們在主标題的頂部更改另一個#include 類依賴于新标題。這是一個問題 - 我們現在必須在所有#include 周圍移動,直到再次正确地排序依賴關系。也許我們在這個過程中引入了一些前向聲明來打破已經出現的循環依賴。整個過程不必要地繁瑣。不,僅包括警衛無法解決它,我們仍然需要在主标題中訂購我們的#includes。
它嚴重誇大了編譯時間。
使用上面的模式,每個源#includes主标頭,并通過目錄中的所有其他标頭。此外,其中一個#include實用工具的主标頭和至少一個其他主标頭的可能性非常大。底線是每個源文件#include包含項目中的每個标頭。并且預編譯頭#include主标頭之一并沒有什麼區别。
所有這些頭文件都包含數千行代碼,必須進行解析和編譯,即使源文件中定義的函數不使用這些類。通過用實際需要的#include替換三個或四個主标題,我們可以将項目的完整構建時間從15分鐘減少到4分鐘以下。仍有很大的潛力可以進一步減少這種情況。
在這種情況下幾乎沒有增量構建
想象一下,我們在這個項目中改變了一些代碼。除非更改僅限于源文件,否則更改将影響每個翻譯單元。它不會影響行為或生成的代碼,但由于我們觸及的标題在任何地方都是傳遞的#include ,構建系統将重新編譯所有内容。15分鐘編譯時間用于在一個地方使用的類的另一個屬性。那是需要很多咖啡。
結論
更多C語言學習内容,請私信 我 “代碼” 獲取
在#include方面不要花哨。使用已被證明運行良好的通用模式:
,
- *使用包含在每一個頭文件保護
- *#包括僅包含您使用定義标題
- *#包括所有包含您使用定義标題-不依賴于傳遞#包括
更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!