gpt4 book ai didi

c++ - 什么决定了两个源文件中同名类包含哪个类定义?

转载 作者:太空狗 更新时间:2023-10-29 23:46:10 25 4
gpt4 key购买 nike

如果我在一个项目中有两个源文件,每个文件都定义了一个同名的类,什么决定了使用哪个版本的类?

例如:

// file1.cpp:

#include <iostream>
#include "file2.h"

struct A
{
A() : a(1) {}
int a;
};

int main()
{
// foo() <-- uncomment this line to draw in file2.cpp's use of class A

A a; // <-- Which version of class A is chosen by the linker?
std::cout << a.a << std::endl; // <-- Is "1" or "2" output?
}

...

//file2.h:

void foo();

...

// file2.cpp:

#include <iostream>
#include "file2.h"

struct A
{
A() : a(2) {}
int a;
};

void foo()
{
A a; // <-- Which version of class A is chosen by the linker?
std::cout << a.a << std::endl; // <-- Is "1" or "2" output?
}

我已经能够让链接器使用相同的代码选择不同版本的 A - 仅通过更改我键入代码的顺序(一路构建)。

诚然,在同一个 namespace 中包含具有相同名称的类的不同定义是糟糕的编程习惯。但是,是否有定义的规则来确定链接器将选择哪个类 - 如果有,它们是什么?

作为这个问题的一个有用的附录,我想知道(通常)编译器/链接器如何处理类——编译器在构建每个源文件时是否将类名和编译后的类定义合并到对象中文件,而链接器(在名称冲突的情况下)丢弃一组已编译的类函数/成员定义?

名称冲突的问题并不神秘 - 我现在意识到它发生在每次只有 header 的模板文件被两个或多个源文件(以及随后的相同模板类)#included被实例化,并在这些多个源文件中调用相同的成员函数),这是 STL 的常见场景。每个源文件必须具有相同实例化模板类函数的单独编译版本,因此链接器必须在链接时选择这些函数的不同此类编译版本),我认为。

-- 关于 Java 的相关问题的附录 --

我注意到各种答案都指出了 C++ 的单一定义规则 ( http://en.wikipedia.org/wiki/One_definition_rule )。有趣的是,我是否正确认为 Java 没有这样的规则 - 因此 Java 规范允许在 Java 中使用多个不同的定义?

最佳答案

如果 C++ 程序提供同一类的两个定义(即在同一命名空间内且命名相同),则该程序违反了标准规则,您将获得未定义的行为。到底发生了什么在某种程度上取决于编译器和链接器:有时您会遇到链接器错误,但这不是必需的。

明显的解决方法是不要有冲突的类名。获取唯一类名的最简单方法是在未命名的命名空间中定义本地使用的类型:

// file1.cpp
namespace {
class A { /*...*/ };
}

// file2.cpp
namespace {
class A { /*...*/ };
}

这两个类不会冲突。

关于c++ - 什么决定了两个源文件中同名类包含哪个类定义?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13388536/

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