假设我在一个程序中有两个编译单元,每个编译单元都声明一个具有相同签名但实现不同的非内联函数,例如
// a.cpp
namespace internal {
int foo(int a) {
return a+1;
}
}
int main() {
}
和
// b.cpp
namespace internal {
int foo(int b) {
return b+2;
}
}
对此进行编译/链接(带有-std=c++11
的g ++ 4.8.3),出现错误
b.cpp:(.text+0x0): multiple definition of `internal::foo(int)'
这是可以预期的,因为据我了解,这完全违反了one definition rule:
每个非内联函数或变量只有一个定义 必须使用奇数个(见下文) 程序(包括任何标准库和用户定义库)。
现在,将namespace internal
更改为未命名的名称空间,该错误消失了。直观上,这对我来说很有意义,因为我正在从external to internal linkage更改函数:
在命名空间范围内声明的以下任何名称均具有外部名称 链接,除非名称空间未命名或包含在名称空间中 未命名的命名空间(自C ++ 11起):未列出变量和函数 上面的(即,函数未声明为静态[...])...
和
[A]在未命名的名称空间或名称空间中声明的名称 在一个未命名的命名空间中,即使是明确声明为extern的命名空间, 有内部联系。
但是,我无法在一个定义规则中找到任何可免除内部链接功能的东西。因此,我的问题是:我的直觉推理是否正确,或者我是否仍然使用具有内部链接的函数违反了一个定义规则(并且编译器/链接器只是不再报告它了)?另外,该标准(或cppreference.com :)
)在哪里说是否还可以?
答案 0 :(得分:2)
n4713
§6.5程序和链接[basic.link]
当一个名称可能表示同一对象时,它被称为具有链接, 引用,函数,类型,模板,名称空间或值作为名称 由声明引入另一个范围:
(2.1)-名称具有外部链接时,其表示的实体可以是 由其他翻译单位范围或 同一翻译单元的其他范围。
(2.2)-名称具有内部链接时,它表示的实体可以 在同一译文中被其他范围的名称所指 单位。
-当一个名称没有链接时,它所表示的实体不能被引用 以其他作用域的名称命名。
这基本上表示(对于未命名的名称空间)foo
中的名称a.cpp
和foo
中的名称b.cpp
分别指不同的实体。因此,您没有同一个对象的两个定义,因此不会违反ODR。