假设我在一个程序中有两个汇编单元,每个程序都声明具有相同签名的非内部函数,但实现方面有所不同,例如
// a.cpp
namespace internal {
int foo(int a) {
return a+1;
}
}
int main() {
}
和
// b.cpp
namespace internal {
int foo(int b) {
return b+2;
}
}
编译/链接此(G 4.8.3与-std=c++11
),我有一个错误
b.cpp:(.text+0x0): multiple definition of `internal::foo(int)'
这是相当预期的,据我所知,这只是对一个定义规则的违反:
每个非内部功能或变量的一个定义 这是使用ODR(见下文)必须出现在整个 程序(包括任何标准和用户定义的库)。
现在,将namespace internal
更改为未命名的名称空间,错误会消失。直观地,这对我来说很有意义,因为我正在将功能从外部链接更改为内部链接:
在名称空间范围上声明的以下任何名称都具有外部 链接,除非命名空间未命名或包含在 未命名的名称空间(自C 11):变量和功能未列出 上面(即,函数未声明为静态[...])...
和
[a] ll名称在未命名的名称空间或名称空间中声明 在一个未命名的名称空间中,即使是明确宣布为外部的空间, 具有内部联系。
但是,我在一个定义规则中找不到任何用内部链接豁免函数的任何内容。因此,我的问题是:我的直观推理是否正确,还是我仍在具有内部链接的函数(以及编译器/链接器不再报告)的一个定义规则?此外,标准(或cppreference.com :)
)在哪里说是可以的?
n4713
§6.5程序和链接[basic.link]
据说一个名称在可能表示同一对象时具有链接, 参考,功能,类型,模板,名称空间或值为名称 由另一个范围内的声明引入:
(2.1) - 当名称具有外部链接时,它表示的实体可以是 由其他翻译单元的范围或来自 同一翻译单元的其他范围。
(2.2) - 当名称具有内部链接时,它表示可以 在同一翻译中以其他范围的名称提及 单位。
- 当名称没有链接时,它表示的实体不能被转介 通过其他范围的名称。
这基本上说(在未命名的名称空间的情况下)a.cpp
的名称foo
和b.cpp
中的名称foo
每个都参考不同的实体。因此,您没有对同一对象的两个定义,因此不违反ODR。