鏈接器對此報告重復的符號:#ifndef testttt#define testtttvoid anything(){ std::cout<<"hellooooooo";}#endif因為它在include防護內部,所以我希望此函數只定義一次。但顯然不是。我知道我可以static在它前面加上這個詞,然后它就會起作用(我仍然覺得很諷刺,因為應該將static賦予它內部鏈接,但是可以從多個cpp文件中使用該函數)。因此,我想我的問題分為兩部分:1)為什么包含保護不像其他標頭項那樣阻止該函數的多個定義,以及2)為什么static當應該假定靜態名稱阻止名稱可見時,單詞會解決此問題嗎?在其他翻譯單位中?我添加了它,實際上可以從包含此頭文件的任何位置調用此函數。
3 回答

皈依舞
TA貢獻1851條經驗 獲得超3個贊
“ 1)為什么包含保護不能像其他標題項那樣阻止該功能的多個定義”
因為每個翻譯單元(即.cpp文件)都是分別處理的,并且要經過相同的條件。翻譯單元不會共享其他翻譯單元遇到的預處理器定義。這意味著將處理該標頭的所有翻譯單元都將包含該函數的定義。當然,鏈接器隨后會抱怨同一函數具有多個定義。
“ 2)當應該使用靜態詞來防止名稱在其他翻譯單元中可見時,為什么靜態詞會解決此問題?”
因為static
關鍵字為每個翻譯單元制作了該功能的私有副本。
但是,如果您希望在共享頭文件中定義該函數,則應將其標記為inline
,這將解決您的問題并使不必要的預處理器防護。

瀟湘沐
TA貢獻1816條經驗 獲得超6個贊
1)為什么包含保護不能像其他標題項那樣阻止該功能的多個定義,
包含保護可防止在同一轉換單元中多次包含標頭。但是,它不能防止出現多個定義:如果標頭包含在多個翻譯單元中,則將存在多個定義錯誤,因為該函數是在每個翻譯單元中定義的,并且由于它具有外部鏈接,因此所有翻譯單元都可以請參閱所有其他翻譯單元的定義。為防止發生此錯誤,您只需在標頭中提供聲明,并在一個文件中提供定義.cpp。
閱讀有關一個定義規則(ODR)和外部鏈接的信息。
2)當應該使用靜態詞來防止名稱在其他翻譯單元中可見時,為什么靜態詞會解決此問題?
因為static使函數在每個翻譯單元內部均有效。這就是內部鏈接的含義:其他翻譯單元看不到定義。
- 3 回答
- 0 關注
- 447 瀏覽
添加回答
舉報
0/150
提交
取消