rcp*_*lus 7 c++ linker class c++11
如果我有一个foo.cpp包含以下代码的文件:
class Foo {
};
class Foo {
};
int main() {
return 0;
}
Run Code Online (Sandbox Code Playgroud)
然后我自然而然error: redefinition of 'Foo'.但是,如果我有foo.cpp带
class Foo {
};
int main() {
return 0;
}
Run Code Online (Sandbox Code Playgroud)
并bar.cpp用
class Foo {
};
Run Code Online (Sandbox Code Playgroud)
尽管class Foo在整个程序中被定义了两次,但整个事情编译得很好.
如果我int something;在全局命名空间中放入了两个文件,那么我会得到一个链接器错误(特别是duplicate symbol),但是对于类定义,这种情况永远不会发生.
我知道函数声明,例如int doIt();可以在两个cpp文件中复制,但是一个定义,例如int doIt() {} 不能.现在,在第一个编译器错误(class Foo{};在一个cpp文件中有两次),它说redefinition of foo,class Foo{};定义也是如此.那么为什么,与功能不同,它可以在一个程序中定义两次?
编辑:根据这个网站,命名类有外部链接.那么为什么class Foo两个cpp文件之间没有冲突呢?
EDIT2:根据上面链接的网站,命名类不仅具有外部链接,而且它也是静态成员.但这一切都很好:
foo.cpp:
class Foo {
public:
int foo();
static int x;
};
int Foo::foo() {
return 5;
}
int main() {
return 0;
}
Run Code Online (Sandbox Code Playgroud)
bar.cpp:
class Foo {
public:
int foo(int);
static bool x;
};
int Foo::foo(int i) {
return i * 2;
}
Run Code Online (Sandbox Code Playgroud)
不仅Foo::foo使用不同的签名重新定义,而且Foo::x具有不同的类型.这两个都应该有外部链接,但这个代码是A-ok.
关于你的第一个问题,多个 TU 具有相同的定义,这是 ODR 明确允许的,因为否则该语言将毫无用处。
关于第二个问题,不同的 TU 有不同的定义,这违反了 ODR。然而,这些都是 NDR。你的程序仍然是畸形的,并且可能会导致奇怪的错误。
关于第三个问题,对于static数据成员来说,那些是声明,而不是定义。他们需要一个独特的定义,例如:
TheType ClassName::VariableName;
Run Code Online (Sandbox Code Playgroud)
这些通常放置在随附的 .cpp 文件中。
有一个例外,即const static具有内联初始值设定项的数据成员。
ODR = 一种定义规则
TU = 翻译单元
NDR = 无需诊断
关于 NDR 的说明;编译器很难检测到某些类型的错误,并且标准通常不要求编译器在这些情况下发出诊断(即警告或错误)。有些工具(例如 CppLint)可以检测到编译器无法检测到的许多错误。当涉及 ODR 违规时,通常可以通过仅在标头中定义类型来避免这些违规。
| 归档时间: |
|
| 查看次数: |
877 次 |
| 最近记录: |