2011-09-07 187 views
7

C++仍然是一種不斷髮展的語言,多年來新增了新功能。C++的模塊概念

我在C++中錯過的一個特性是一個正確的模塊概念:使用頭文件的當前方法(使用條件#define來確保頭文件不包含兩次)似乎絕對不令人滿意。

例如,在我的項目中,我們遇到了許多源文件中包含太多「#include」的問題,這使得編譯時間不必要很長:使用Incredibuild需要45分鐘來構建我們的產品並行使用至少10個內核。因此,我們不得不花費大量的時間來手動清理文件,即刪除包括檢查它們是否真的需要。

我認爲這將是有一個模塊的概念,能夠

  1. 明確分開從模塊的實現接口是非常有用的;
  2. 單獨編譯接口和模塊的主體(當前.h文件每次被包含在其他文件中時會被重複編譯):一個工具可以讀取已編譯的接口,並告訴它的類型,函數,類出口;
  3. 編寫工具可以更輕鬆地自動重新排列導入(例如,使用Java/Eclipse可以自動重新排列文件的所有導入)。

您是否認爲有可能定義這樣的模塊概念並將其整合到C++中,或者這會太複雜?你知道這方面的努力嗎?

編輯

感謝有關預編譯頭的建議。如果可能的話,我會嘗試一下(我們使用Visual Studio 2008)。 也許我們以錯誤的方式使用頭文件(?)我們爲每個類使用一個頭文件。然後我們有一個類實現的cpp文件。通常我們最終得到包含30,40個頭文件的cpp文件。當我們更改cpp文件時,一些包含不再需要,但很難找出哪些包含。這部分與頭文件包含其他頭文件有關。

我們花費太多時間重新整理導入,看起來不存在可自動執行此操作的工具。這會爲我們節省很多時間。

+0

我想查看搜索工具包括樹包括不包含任何使用的符號。當源文件發生變化時,很難保持包含清潔。 – Salw

+1

我不確定你的第一句話是否屬實。 C++ 11標準很早以前就已定稿,不久前接受並在上週發佈;我懷疑現在有人在添加功能。 –

+0

@Kerrek SB:我已經改變了刪除對C++ 0x的引用的文本。感謝您的建議。 – Giorgio

回答

10

C++仍然是一種不斷髮展的語言,新功能被添加到 它作爲C++ 0x開發的一部分。

C++ 11標準has already been approvedpublished,所以沒有更多的功能被添加到它。至少還有幾年沒有。

一個功能,我在C++錯過不好是一個適當的模塊概念: 當前使用方法的頭文件(如您使用條件 #define確保頭不包括兩次)似乎 絕對不能令人滿意對我來說。

一些編譯器支持#pragma once以避免寫的包括警衛,但它是非標準的,據我所知。有不要想要包括警衛; Boost.Preprocessor是一個圖書館的例子,它有些標題故意沒有包含警衛。

例如,在我的項目,我們有,我們有很多的源文件太多 「的#include」的問題,使編譯時間 不必要的長:它需要45分鐘,以打造我們的產品,使用 Incredibuild,即並行使用至少10個內核。因此,我們 必須花費大量的時間手動清理文件,即刪除 包括檢查是否真的需要。

Stroustrup has an FAQ entry on compile-time slowness。另請閱讀GotW article #7關於包含頭文件。這很可能是你包含的文件多於必要的方式。例如,您可能能夠擺脫前向聲明。如果你有很大的頭文件,你可以嘗試把它們分開,這樣你的源代碼就只包含你真正需要的聲明。這可能只是你的文件結構不利於快速編譯的問題。

1,明確分離模塊的實現接口;

我們有the PIMPL idiom(也稱爲編譯防火牆)。即使沒有它,我也沒有任何麻煩,將文件中的實現和.h文件中的接口(儘管它不是一個「純粹」接口)放在.cpp文件中。

2.compile的接口和模塊分別 體(目前.h文件再次編譯和重新每次他們 包含在其他文件):一個工具可以再讀取編譯 接口和告訴它輸出的是什麼類型,功能,類別;

一些編譯器支持precompiled header files,您可以利用它。

3.用於自動重新排列輸入的工具更容易。

我不明白你的意思。

你認爲它可以定義這樣的模塊概念, 它集成到C++或會認爲太複雜?你知道任何 這方面的努力嗎?

不管你信不信,有a proposal添加某種模塊概念到C++的,但它並沒有被接納進入C++ 11由於時間的限制(他們工作和審查其他建議像右值在我看來,參考文獻更重要)。它可能包含在下一個版本或C++標準的更新中。

+2

我肯定會給預編譯頭文件一個鏡頭。如果你有一個正常的增量構建系統(而不是整夜構建),那麼長包頭是編譯時間的很大一部分,並且PCH可以真正地減少它。 –

+0

據我所知,很難編寫一個自動重新導入C++文件中的導入工具,這與C++包含機制有關。我在Eclipse/C++網站上發現了一些關於此的討論。如果可以引起興趣,我可以挖掘鏈接。 – Giorgio

+0

感謝您提交提案的鏈接。 – Giorgio

0

這不是C++設計工作的方式。你可以做到這一點,如果你戳和鏈接器足以讀取索引文件,而不是重新解析頭。但是,編譯器應該只編譯已更改的文件或依賴項已更改的文件。此外,頭文件並不真正「編譯」成有意義的代碼(除非它們具有實現,在某些情況下這是正確的)。它們只是給編譯器的一個提示,說明這個標記在鏈接後會被發現。

簡答:不,你不應該嘗試實施一些自制的「模塊」系統。我真的懷疑頭文件是永久採取的,除非你錯誤地使用它們。

編輯:正如有人指出的,我忽略了可能實際上有東西需要編譯的頭文件,這通常是大型庫或任何使用大量模板的情況。因此,我錯誤地認爲「真正懷疑頭文件是永久存在的」語句。

+0

我有一個簡短的程序來創建一個PNG與Boost.GIL。編譯需要10秒鐘。預編譯頭文件(大約60MB的pch文件)將其縮減到幾分之一秒。 –

+0

哇......看來現在是我把腳插入嘴巴的時候了。我猜標題實際上可能比我想象的要多得多。 (尤其是模板厚的標題。) – Corbin

+1

特別是那些討厭的Boost標題! :-) –