2014-09-30 168 views
0

讀完Why do we need extern "C"{ #include <foo.h> } in C++?我得出的結論是,在extern「C」塊內包含一個頭是很好的。混合C/C++頭文件可以包含另一個混合頭文件嗎?

但我遇到了這個問題星座:

#ifdef __cplusplus 
extern "C" { 
#endif 

#include "mixedstuff.h" 

#ifdef __cplusplus 
} 
#endif 

mixedstuff.h:

#ifdef __cplusplus 
extern "C" { 
#endif 

#include "cstuff.h" 

#ifdef __cplusplus 
} 
#include "cppstuff.h" 
#endif 

正如人們所看到的,我結束了cppstuff.h被列入由extern "C"內的C++編譯器塊。這導致了很多錯誤,因爲許多陳述在C-linkage中是不可能的。

明顯的解決辦法是在以外的extern "C"塊。但是這需要我查看每個頭文件,看它是否是純C++或混合的。

從這我推薦使標題C++意識到,而不是將它們包含在extern「C」中。我是對的,還是有更好的方法?

+0

__cplusplus的第一次使用是不必要的,因爲包括.h文件已經照顧它。這當然解決了這個問題。不要太多:) – 2014-09-30 15:15:18

+0

這就是我的意思是「明顯的解決方案」。我試圖尋求這種情況下的最佳做法。 – Sascha 2014-10-01 07:29:51

回答

2

從您的描述中,我收集到mixedstuff.h被設計爲 以用於C和C++。這意味着它可能有 #ifdef __cplusplus等,在一些純粹的C++代碼的地方。 在這種情況下,應將而不是包含在extern "C"塊內。一般情況下,除非另有明確說明,否則大部分標題應包含在最外層,而不包括所有塊,名稱空間等 。 C++;那些必須包含在extern "C" 區塊內。 (但是從我所看到的情況來看,這樣的標題更爲罕見 和更罕見)。

而且你不應該看看標題;你需要看文檔。

如果你是頭文件的作者,那麼你應該讓C++知道(並且記錄這個事實,也許在庫級別)。

1

當這個例子告訴你把extern "C"放在你自己的時候,那就是當你包含一個純C標頭時。

因爲它只是C語言,所以它可能用C語言編寫,因此如果您想將它用於C++,則需要將它指定爲C標頭。

如果你有mixstuff.h它不會在C中工作,因爲它只有C++構造。那些是C結構的C結構,您應該在mixstuff.h中明確標記。或者將它們隔離到自己的標題中。

請注意,與mixstuff.h一起,將會有某個mixstuff.cmixstuff.cpp被編譯,或者甚至可能是兩個不同的編譯單元。您可以使用C++編譯器來編譯實現,甚至可以使用C++(使用C鏈接)在它們的實現中使用C++構造(通常,您將經常爲C++庫提供C接口)。

如果mixstuff最初使用C++構建,並且C++的名稱會被重新編譯,如果現在將extern "C"放在聲明的附近,它將不會與您的代碼鏈接。如果這些函數確實是由C編譯器構建的,則需要使用extern "C"以便您可以看到它們。

1

有各種C和C++標準,它們有共同點和不同之處。

如果代碼是在所有目標標準的通用交集中編寫的,只需將其包含在全局名稱空間中即可。

如果在C++中只包含extern "C",則將其包裝在外部。

否則,事情變得複雜,你必須直接修補它。

預處理器,對__cplusplus__STDC_VERSION__和其他特徵 - 與語言測試宏條件,是編寫代碼,其更廣泛的一系列比由一般語言本身保證的條件下適當的行爲的方法。

明智地使用它,很容易被誤用。

+0

+1「明智地使用它,很容易被濫用。」我現在讀了一些關於外部「C」的結構,並沒有發現這樣的警告詞。 – Sascha 2014-10-01 07:31:00

1

如果你想確保東西有C++聯動即使包含頭文件可能包括一個extern "C"塊裏面,你可以使用extern "C++"塊:

extern "C++" { 
#include "cppstuff.h" 
}