gpt4 book ai didi

c++ - 为什么跨 cpp 文件定义类不会导致链接器错误?

转载 作者:可可西里 更新时间:2023-11-01 18:38:56 26 4
gpt4 key购买 nike

如果我有一个包含以下代码的文件 foo.cpp:

class Foo {
};

class Foo {
};

int main() {
return 0;
}

然后我自然会得到 error: redefinition of 'Foo'。但是,如果我有 foo.cpp

class Foo {
};

int main() {
return 0;
}

bar.cpp

class Foo {
};

尽管 class Foo 在整个程序中被定义了两次,但整个程序编译正常。

如果我将 int something; 放在全局命名空间的两个文件中,那么我会得到一个链接器错误(特别是 duplicate symbol),但对于类定义,这永远不会发生。

我知道像 int doIt(); 这样的函数声明可以在两个 cpp 文件中重复,但是定义,例如int doIt() {} 不能是。现在在第一个编译器错误中(class Foo{}; 在一个 cpp 文件中两次),它说 redefinition of foo,所以 class Foo{}; 是一个定义。那为什么不像函数,可以在一个程序中定义两次呢?

编辑:根据this website ,命名类具有外部链接。那么,为什么两个 cpp 文件中的 class Foo 之间没有冲突呢?

EDIT2:根据上面链接的网站,不仅命名类具有外部链接,静态成员也是如此。然而这一切都编译得很好:

foo.cpp:

class Foo {
public:
int foo();
static int x;
};

int Foo::foo() {
return 5;
}

int main() {
return 0;
}

bar.cpp:

class Foo {
public:
int foo(int);
static bool x;
};

int Foo::foo(int i) {
return i * 2;
}

不仅 Foo::foo 被重新定义为不同的签名,而且 Foo::x 也属于不同的类型。这两个都应该有外部链接,但这段代码是 A-ok。

最佳答案

关于您的第一个问题,各个方面的定义相同多个 TU,这是 ODR 明确允许的,否则语言将毫无用处。

关于第二个问题,不同的地方有不同的定义恩,这是 ODR 违规行为。但是,这些是 NDR。你的程序是仍然是畸形的,它可能会导致奇怪的错误。

关于第三个问题,对于static数据成员,那些是声明,而不是定义。他们需要一个独特的定义,例如:

TheType ClassName::VariableName;

这些通常放在随附的 .cpp 文件中。

有一个异常(exception),const static 数据成员有内联初始化程序。


ODR = 一个定义规则
TU = 翻译单位
NDR = 无需诊断

关于 NDR 的注释;某些类型的错误对编译器来说很难检测,标准通常不要求编译器在这些情况下发出诊断(即警告或错误)。有工具,例如 CppLint,可以检测编译器的许多错误不能。当涉及到 ODR 违规时,这些通常是可以避免的通过仅在 header 中定义类型。

关于c++ - 为什么跨 cpp 文件定义类不会导致链接器错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43463345/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com