2011-05-17 68 views
4

我目前正在編寫一個程序,但無法弄清楚爲什麼我得到一個錯誤(注意:我已經修復了它,我很好奇爲什麼錯誤在那裏,這意味着包括.h文件)。C++包含一個「.h」文件,函數重複混淆

基本上,我的程序結構如下:

當前文件我的工作,我會打電話給Current.cc(這是Current.h實現)。

Current.cc包含一個頭文件,名爲CalledByCurrent.h(它有一個相關的實現,名爲CalledByCurrent.cc)。 CalledByCurrent.h包含一個類定義。

CalledByCurrent.cc中定義了一個非類功能,稱爲thisFunction()thisFunction()未在CalledByCurrent.h中聲明,因爲它實際上不是該類的成員函數(只是一個小幫助函數)。在Current.cc中,我需要使用這個函數,所以我剛剛在Current.cc的頂部重新定義了thisFunction()。但是,當我這樣做時,我得到一個錯誤,說該函數是重複的。爲什麼這個,當myFunction()甚至沒有在CalledByCurrent.h宣佈?

因此,我剛剛從Current.cc中刪除了該功能,現在假設Current.cc已從CalledByCurrent.cc訪問thisFunction()。但是,當我這樣做時,我發現Current.cc不知道我在說什麼功能。有沒有搞錯?然後,我將thisFunction()的函數定義複製到我的CalledByCurrent.h文件的頂部,這解決了問題。你能幫我理解這種行爲嗎?特別是,它爲什麼會認爲有重複,但它不知道如何使用原件?

p.s - 我很抱歉這篇文章有多混淆。請讓我知道,如果有什麼我可以清理。

+0

簡化你的帖子的一個好主意是發佈一個小樣本文件,顯示Current.cc,CalledByCurrent.cc和它的頭文件的內容。 – VinGarcia 2017-12-19 19:31:04

回答

3

不能有兩個具有相同名稱的全局函數(即使在2個不同的翻譯單元中)。爲避免發生鏈接器錯誤,請將函數定義爲static,以便在翻譯單元外部不可見。

編輯

您可以通過使用關鍵字extern使用該功能在其他.cpp文件。看到這個例子:

//Test.cpp 

void myfunc() 
{ 

} 

//Main.cpp 
extern void myfunc(); 
int main() 
{ 
    myfunc(); 
} 

它會調用test.cpp定義myfunc()

+0

[Neil Butterworth's answer](http://stackoverflow.com/questions/6027371/c-including-a-h-file-function-duplication-confusion/6027412#6027412)就是一個例子。 – 2011-05-17 07:11:54

+0

謝謝。所以我明白爲什麼會有重複的錯誤。我不明白的是,爲什麼當我從Current.cc中刪除重複項時,我無法使用thisFunction()(儘管重新聲明它會導致重複錯誤)。 – 2011-05-17 07:37:49

+0

@Casey P:你可以使用'extern'來達到這個目的。查看編輯。 – Asha 2011-05-17 07:53:26

0

這裏有一些想法:

  • 你沒有把header include guard在你的頭文件。如果包含兩次,您可能會遇到這種錯誤。
  • 該函數的原型(頂部)與其簽名100%不匹配。
  • 您將正文的函數放在頭文件中。
  • 在兩個不同的源文件中,您有兩個具有相同簽名的功能,但它們未標記爲static

如果你正在使用gcc(你沒有說你正在使用的編譯器),你可以使用-E開關,查看預處理器輸出。這包括擴大所有#define和包括所有#include s。

每次展開某件東西時,它都會告訴你它在哪個文件和行中。使用此功能可以看到在哪裏定義了thisFunction()

+0

即使沒有標頭警衛,也會發生此錯誤。您可以嘗試在2個不同的cpp文件中編寫一個空函數並將它們一起編譯。 – iammilind 2011-05-17 07:13:04

+0

沒錯。我將編輯我的答案以反映這種其他可能性 – 2011-05-17 07:14:12

4

您正從鏈接器獲取多個定義 - 它看到具有相同名稱和抱怨的兩個函數。例如:

// a.cpp 
void f() {} 

// b.cpp 
void f() {} 

然後

g++ a.cpp b.cpp 

給出:

C:\Users\neilb\Temp\ccZU9pkv.o:b.cpp:(.text+0x0): multiple definition of `f()' 

這一輪的方法是要麼把定義中只有一個.cpp文件,或宣佈一個或兩個作爲靜態功能:

// b.cpp 
static void f() {} 
+0

但是,爲什麼當myFunction()僅包含在CalledByCurrent.cc中而不包含在.h中時,它會看到兩個具有相同名稱的函數?此外,爲什麼當我從Current.cc中刪除重複項時,是不是可以使用CalledByCurrent.cc中的函數? – 2011-05-17 07:11:13

+0

@ The C Man因爲跨文件解析名稱是鏈接器所做的。 – 2011-05-17 07:14:13

+0

因此,鏈接器只是檢查名稱,而不是實際的可用性?因此,儘管Current.cc實際上不能使用該函數,但鏈接器可能會將其視爲重複項。 – 2011-05-17 07:40:44

1

頭文件包含機制應該可以容忍重複的頭文件包含。

+0

這是真的,但上述錯誤與多頭包含無關。 – Asha 2011-05-17 07:58:31

1

這是因爲無論何時您只需聲明一個函數,就會在extern(全局)範圍內考慮(無論您是否在頭文件中聲明它)。鏈接器對於相同的函數簽名將有多個實現。

如果這些函數是真正的輔助函數,那麼聲明它們爲;

static void thisFunction(); 

其他方式,如果你使用的是相同的功能,助手,那麼,簡單地宣佈它在一個共同的頭文件,說:

//CalledByCurrent.h (is included in both .cc files) 
void thisFunction(); 

而且在任的執行thisFunction()。 cc文件。這應該正確地解決問題。

0

有兩個不同的錯誤來自構建的兩個不同階段。

在第一種情況下,你有一個重複的,編譯器很高興,但LINKER抱怨,因爲當它在不同的源文件中找到所有函數定義時,它的命名相同。在其他答案的狀態中,您可以使用static關鍵字或使用通用定義。

在第二種情況下,你看到你的函數沒有在這個範圍內聲明,這是因爲COMPILER在抱怨,因爲每個文件都需要知道它可以使用哪些函數。

編譯發生在鏈接之前,因此編譯器無法提前知道鏈接器是否會找到匹配的函數,這就是爲什麼您使用聲明來通知編譯器稍後LINKER會找到定義。你可以看到,你的2個錯誤並不矛盾,它們是構建中有2個獨立進程的結果,它們有特定的順序。