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

我注意到当有递归函数时,编译器通常会忽略内联声明。但我的问题是为什么如果我删除内联声明,我可以这样做:

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) 的多个定义

4

3 回答 3

1

因为当您使用 时#include "Q2a.h",您实际上是在对内容进行文本替换,所以 Q2a.cpp 和 Q2b.cpp 最终都定义了一个名为 的函数MyFactorial()。您要么需要使用inline,要么在其中一个源文件中定义函数。

请注意,使用inline对递归函数没有多大帮助!

于 2010-09-05T19:32:58.777 回答
1

使用 GCC 声明一个函数 asinline只会提示编译器内联该函数。但是,编译器仍会生成一个非内联函数,您可以从不同的编译单元调用该函数。

在您的情况下,这些函数有名称冲突。简单地说:内联并不意味着静态。

你想要做的是将函数声明为static inline

这将告诉编译器您希望您的函数内联,并且 - 如果编译器决定内联它 - 不需要相同函数的静态版本。如果编译器不能内联函数,它将确保函数是静态的,例如,函数的名称是 C 文件的本地名称,并且在程序链接期间不会发生名称冲突。

暗示:

编译器有不同的行为。如果您以后想在不同的平台上编译代码,请确保将定义隐藏在宏中。

例如,我必须使用static inlineGCC 和 Visual Studio 以及一个简单_inline的 TI Code Composer DSP/嵌入式 ARM 编译器。后来的编译器不理解普通的内联,因为它是非标准的,也不会理解静态 _inline。

于 2010-09-05T20:11:04.423 回答
1

当你声明一个函数时inline,你改变了适用于你的函数定义的规则。

一个非inline函数只能在程序中定义一次;相反,一个inline函数可以在多个翻译单元中定义,尽管定义必须相同,并且该函数必须在使用它的每个翻译中定义。

By removing inline, you are removing the exemption from the "one definition rule" that you had previously.

于 2010-09-05T21:28:46.793 回答