2010-09-05 83 views
1

我有這個文件:遞歸內聯函數

//Q2a.h 
#ifndef Q2A_H 
#define Q2A_H 

inline int MyFactorial(int a) 
{ 
if (a < 2) 
    return 1; 
return a*MyFactorial(a-1); 
} 

int NumPermutations(int b); 
#endif 

//Q2a.cpp 
#include "Q2a.h" 

int NumPermutations(int b) 
{ 
    return MyFactorial(b); 
} 

and file with the main- Q2b.cpp 

我注意到,編譯器通常會忽略當有遞歸函數內聯decleration。 但我的問題是爲什麼,如果我刪除inline聲明,我可以這樣做:

g++ -Wall -g -c Q2a.cpp -o Q2a.o 
g++ -Wall -g -c Q2b.cpp -o Q2b.o 

這些都很好,但在聯動階段:

g++ -Wall -g -c Q2a.o Q2b.o -o Q2 

我得到一個錯誤:的'多重定義MyFactorial(int)

回答

1

因爲當你#include "Q2a.h",你基本上是做內容的文本替換,所以Q2a.cpp和Q2b.cpp最終定義了一個叫做MyFactorial()的函數。您需要使用inline,或者在其中一個源文件中定義該功能。

請注意,使用inline對遞歸函數無助!

+0

尾遞歸'inline'是合理的,但這不是這種情況。 – Potatoswatter 2010-09-05 21:06:10

1

GCC聲明一個函數爲inline只會提示編譯器內聯該函數。但是,編譯器仍然會生成非內聯函數,您可以從其他編譯單元調用該函數。

這些函數在您的情況下有名稱衝突。簡單地說:內聯並不意味着靜態。

你想要做什麼是聲明功能static inline

這會告訴你希望你的函數內聯和編譯器 - 如果編譯器確定內聯它 - 同樣的功能沒有靜態版本需要。它使編譯器不能內聯函數,它會確保函數是靜態的,例如,該函數的名稱是C文件的本地名稱,並且在程序鏈接過程中不會發生名稱衝突。

提示:

編譯器有不同的行爲。如果您希望將來在其他平臺上編譯代碼,請確保將該定義隱藏在宏中。

例如,我必須爲GCC和Visual Studio使用static inline,爲TI Code Composer DSP /嵌入式ARM編譯器使用簡單的_inline。後面的編譯器不能理解內聯的plain,因爲它是非標準的,並且不會理解static _inline。

+0

來自標準:「7.1。1存儲類說明符 - 存儲類說明符是 存儲類說明符: 'auto register static extern mutable' **至多一個存儲類說明符應出現在給定的decl-specifier-seq中。「* * – Potatoswatter 2010-09-05 21:10:00

+0

'inline'就像靜態一樣,但是如果函數定義完全相同,'static'說「這將在多個文件中定義,可能是不同的。 'inline'表示「這將在多個文件中交替定義。」代碼生成提示是次要的效果。 – Potatoswatter 2010-09-05 21:11:13

1

當您聲明函數inline時,您將更改適用於您的函數定義的規則。

一個非inline函數只能在程序中定義一次;相反,功能可以在多個翻譯單元中定義,但是定義必須是相同的,並且必須在其使用它的每個翻譯中定義該功能。

通過刪除inline,您將免除您之前的「一個定義規則」。