我无法理解以下行为:一个标题包含一些基本类型,另一个标题我在几个函数中使用这些类型。之后我开始根据我定义的类型和函数构建类。如果我留下以下签名,则在函数头中:
void whateverFunction(parameters)
链接器指出whateverFunction有多个定义。现在如果将其更改为:
inline void whateverFunction(parameters)
链接问题已经消失,所有编译和链接都很好。我所知道的内联是它用它的代码替换每个函数调用,而不是它非常暗,所以我的问题是:
链接器如何处理C ++中的内联函数?
答案 0 :(得分:25)
如果标题中的函数不是内联的,则此函数的多个定义(例如,在多个翻译单元中)违反了ODR规则。
默认情况下,内联函数具有外部链接。因此,作为ODR规则的结果(如下所示),这样的多个定义(例如,在多个翻译单元中)是好的:
$ 3.2 / 5-“可以有不止一个 类类型的定义(第9条), 枚举类型(7.2),内联 具有外部链接的功能 (7.1.2),课堂模板(第14条), 非静态函数模板(14.5.6), 类模板的静态数据成员 (14.5.1.3),类的成员函数 模板(14.5.1.1)或模板 专门化为哪些模板 参数未指定(14.7, 14.5.5)在程序中规定每个定义出现在不同的中 翻译单位,并提供 定义满足以下要求 要求。鉴于这样的实体 命名D在多个中定义 翻译单位,然后
- D的每个定义都包括在内 相同序列的令牌;和[...]
链接器如何处理内联函数是一个非常多的实现级细节。只需知道实施在ODR规则的限制范围内接受多种定义
即可请注意,如果标题中的函数声明更改为“static inline ....”,则内联函数显式具有内部链接,并且每个翻译单元都有自己的静态内联函数副本。
答案 1 :(得分:9)
链接器可能根本看不到内联函数。它们通常直接编译到调用它们的代码中(即代码用于代替函数调用)。
如果编译器选择不内联函数(因为它只是一个提示),我不确定,但我认为编译器将其作为普通的非内联函数发出并以某种方式对其进行注释,以便链接器选择它看到的第一个副本并忽略其他副本。
答案 2 :(得分:0)
内联只是掩盖了问题。有多个定义可以解决某个问题。
Juste小心你如何使用标题。别忘了:
- << #ifndef HEADER_NAME
/ #define HEADER_NAME
/ #endif
>>避免多重包容。
- 不要使用间接包含:如果在文件中使用类型,请添加相应的标题,即使同一文件中的另一个标题包含它也是如此。