2017-01-04 120 views
1

有一本C++書籍說我們需要在兩個不同的文件中包含兩個頭文件,一個帶有一個類,另一個帶有使用前一個文件中的類的main()。C++ #include headers

這裏的報價:

因爲我們SALES_DATA類有一個字符串成員,Sales_data.h必須#字符串頭。使用Sales_data的程序也需要包含字符串標題。

但有些東西我不明白。如果我們在主文件中包含「Sales_data.h」,#include <(string)>已經在這個頭文件中,所以不需要在我們的主文件中包含#include <(string)>。

據我所知,當我們在一個主文件中包含一個文件時,C++只會複製並粘貼文件頭部調用的整個文件。因此添加第二個#include <(string)>是不必要的。我正在談論當頭部沒有#ifndef或#define時會發生什麼。

我自己做了測試,我只需要在一個文件中編寫#include <(字符串)>並且它工作。除了頭文件中的#pragma一次之外,我在任何一個文件中都沒有#指令。

+0

您通常不想依賴哪個標題包含哪些其他標題。如果你的模塊使用'std :: string',則#include ',即使你的模塊包含的其他頭文件也包含字符串。由於這個原因,標題包括警衛。 –

+0

儘管有可能你可以穿過街道而不是兩邊看,也沒有什麼可怕的事情發生,但你可以說「在你穿過街道之前你必須兩面看」是完全合理的。如果'Sales_data.h'稍後更改爲不包含'string',會發生什麼情況? –

+0

在技術上它不是必需的,但沒有傷害 – pm100

回答

2

你讀的描述是假的。如果類C的定義使用類型T,例如std::string,那麼該類型需要可用。一般(除與Microsoft代碼),它定義C包括定義的C T.客戶機代碼標題中的標題,然後只需要包括限定C.

的情況與以上的任意間接頭夾雜物不同的報頭。假設C類不使用std::string,但其標題包含<string>。然後,如果使用了C代碼,還使用std::string,這是很好的做法,讓你的代碼還包括<string>。即使在代碼演化的當前階段沒有必要。

客戶端代碼的情況下,包括必要的頭文件,至少與前微軟風格一樣,它本身可以提供更快的構建(構建期間文件訪問更少),並支持通過原始工具進行一些構建優化,例如Visual C++的預編譯頭文件,所有需要預編譯的頭文件需要被收集到一個大的所有頭文件中。反對這種做法的情況是,它需要更多的維護工作。所有編程的80%都是維護。

+1

除PCH外,標準庫頭可能只包含一個內部頭,用於定義它所需的組件,而不是整個事物。我記得看到幾個關於包含使用'std :: string'的SO問題,但在MSVC中只包含一個不定義流插入/提取操作符的內部頭文件('xstring' IIRC)。 –

0

考慮以下情況:Sales_data.h修改爲使用的std::string正向減速的情況(而不是從系統的頭越來越std::string的減速)。這將允許Sales_data.cSales_data.h編譯,但隨後會導致上的任何文件的編譯錯誤包括Sales_data.h,使用std::string,但不包括<string>

假設您可以從其他頭文件間接獲取此頭,但是這不是您應該依賴的東西。我相信作者認爲這是最佳做法。

+0

該類有一個'std :: string'數據成員;它不能使用前向聲明。 –

+0

如果類型不是在減速以外的任何地方使用,它可以在標題中。源代碼將包含標題。 –

+0

** - 1 **聲明數據成員可以用不完整類型聲明,在這種情況下是不正確的和非常誤導的。 –

0

這句話使用SALES_DATA

程序還需要包括字符串頭。

可以被解釋爲(指出任何使用Sales_data的程序都包含字符串標題,因爲它包含在Sales_data標題中。

當然,一個類應該包含所有必需的頭文件。

0

該聲明的問題是有兩個不同的情況應該加以區分,但聲明會將它們混淆在一起。

情況1:

// Foo.h 
#include <string> 
class Foo { 
    std::string member; 
public: 
    Foo() { member = "Hello, world"; } 
}; 

情況2:

// Foo.h 
#include <string> 
class Foo { 
public: 
    std::string Hi() const { return "Hello, world"; } 
}; 

在第一種情況中,<string>列入是暴露的實現細節。實施可能會改爲使用std::vector<char>代替。在第二種情況下,std::stringclass Foo的接口的一部分,不再是實現細節。

在第二種情況下,只有在第二種情況下,你可以依靠<string>被列入"Foo.h"

+0

我喜歡這個區別。但我認爲,在C++中,試圖確定'Foo.h'包含的頭是否歸因於案例1或案例2是不切實際的,以便獲得有時不包括頭的好處。我認爲重要的是,通過合理的編碼實踐,人們應該能夠使用'Foo.h'而不必包含任何支持頭文件。 –