2010-09-05 84 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,您将免除您之前的“一个定义规则”。