C++ 当使用CMake和c+;编译时,如果两个头共享相同的名称,会发生什么情况+;?

C++ 当使用CMake和c+;编译时,如果两个头共享相同的名称,会发生什么情况+;?,c++,cmake,compilation,g++,C++,Cmake,Compilation,G++,给定以下目录结构: 请注意,有两个文件名为System Libraries.hpp 我目前包括以下两种情况: #include "System-Libraries.hpp" 很明显,这里有一个模棱两可的地方。这个项目是编译和运行的,所以系统目前似乎找到了正确的头,但我不认为这是因为定义的行为,我想我只是运气好 CMake、Make和g++如何确定这两个文件中的哪一个将用于编译给定的cpp 请注意,我不是问如何修复它,修复它涉及更改头名称,使其不同,或者包括包含的相对路径,这不是我担心的。我想

给定以下目录结构:

请注意,有两个文件名为
System Libraries.hpp

我目前包括以下两种情况:

#include "System-Libraries.hpp"
很明显,这里有一个模棱两可的地方。这个项目是编译和运行的,所以系统目前似乎找到了正确的头,但我不认为这是因为定义的行为,我想我只是运气好

CMake、Make和g++如何确定这两个文件中的哪一个将用于编译给定的cpp


请注意,我不是问如何修复它,修复它涉及更改头名称,使其不同,或者包括包含的相对路径,这不是我担心的。我想知道为什么CMake和g++都不抱怨两个文件的名称相同,并且包含在同一个最终可执行文件中。

预处理器按以下顺序搜索包含文件:

引用表格:

  • 与包含#include语句的文件位于同一目录中
  • 在当前打开的包含文件的目录中,按与打开顺序相反的顺序。搜索从父包含文件的目录开始,然后继续向上搜索任何祖辈包含文件的目录
  • 沿着每个/I编译器选项指定的路径
  • 沿着INCLUDE环境变量指定的路径
角括号形式:

  • 沿着每个/I编译器选项指定的路径
  • 在命令行上进行编译时,沿着INCLUDE环境变量指定的路径进行

预处理器按以下顺序搜索包含文件:

引用表格:

  • 与包含#include语句的文件位于同一目录中
  • 在当前打开的包含文件的目录中,按与打开顺序相反的顺序。搜索从父包含文件的目录开始,然后继续向上搜索任何祖辈包含文件的目录
  • 沿着每个/I编译器选项指定的路径
  • 沿着INCLUDE环境变量指定的路径
角括号形式:

  • 沿着每个/I编译器选项指定的路径
  • 在命令行上进行编译时,沿着INCLUDE环境变量指定的路径进行

复制品来自:?@Amadeus这是怎么复制的?我的问题与相关问题无关。我不是问“”和包含标题时的区别。我在问当你有两个同名的不同标题时,你读过这一部分吗:对于#include“filename”,预处理器首先在与包含指令的文件相同的目录中搜索?这就是你的答案。编译器查看源文件所在的目录。此目录可能是更接近的dup:。我不确定CMake在这个问题上是否有实质性影响。这是一个驻留在编译器和预处理器中的问题;不是驱动编译过程的工具。我猜它只会包含它找到的第一个文件名。我以前在一个项目中遇到过这个问题,当我在我的
CMakeList.txt
中更改
include\u目录的顺序时出现了这个问题。复制自:?@Amadeus这是如何复制的?我的问题与相关问题无关。我不是问“”和包含标题时的区别。我在问当你有两个同名的不同标题时,你读过这一部分吗:对于#include“filename”,预处理器首先在与包含指令的文件相同的目录中搜索?这就是你的答案。编译器查看源文件所在的目录。此目录可能是更接近的dup:。我不确定CMake在这个问题上是否有实质性影响。这是一个驻留在编译器和预处理器中的问题;不是驱动编译过程的工具。我猜它只会包含它找到的第一个文件名。我以前在一个项目中遇到过这个问题,当我在
CMakeList.txt
中更改
include\u目录的顺序时出现了这个问题。它比这个稍微复杂一点,因为它依赖于实现。这些细节是特定于编译器的。你真的必须说出你在说哪个编译器。根据语言定义,
#include
“搜索一系列实现定义的位置以查找标题”(注意,它说的是“标题”,而不是“文件”;标题不必是文件),
#include“…”
以实现定义的方式搜索“源文件…”,如果搜索失败,指令被重新处理,就好像它使用了
而不是
“…”
。因此,您必须始终依靠实现细节来了解正在发生的事情。它比实现细节要复杂一些,因为它依赖于实现。这些细节是特定于编译器的。你真的必须说出你在说哪个编译器。根据语言定义,
#include
“搜索一系列实现定义的位置以查找标题”(注意,它说的是“标题”,而不是“文件”;标题不必是文件),
#include“…”
以实现定义的方式搜索“源文件…”,如果搜索失败,指令被重新处理,就好像它使用了
而不是
“…”
。因此,您必须始终依靠实现细节来了解发生了什么。