【问题标题】:VS2008: Can I build a project with 2 CPP files of the same name in different folders?VS2008:我可以用不同文件夹中的2个同名CPP文件构建一个项目吗?
【发布时间】:2011-01-17 21:37:01
【问题描述】:

这是我的文件夹结构:

/
|
 -- program.cpp
 -- utility.h
 -- utility.cpp
|
 -- module/
    |
     -- utility.h
     -- utility.cpp

// Note that I have two files named utility.h and two named utility.cpp

在构建项目时,我收到一个链接错误(LNK2028:未解析的令牌等...),说明某些符号未定义。我已经确认所有符号都已定义,并且所有声明的函数都有相应的定义。

我感觉在编译我的项目时,两个文件夹中的utility.cpp 文件被编译到输出文件夹中的相同utility.obj 中。结果,一个会覆盖另一个。

  1. 这是预期的行为吗?
  2. 我该怎么做 构建一个 C++ 二进制文件,它有两个 具有相同名称的文件(尽管在 不同的文件夹)?

【问题讨论】:

  • 你要找的是命名空间
  • @fuzzy:这与命名空间无关。 2 个 .obj 文件中只有一个被拉入链接步骤。
  • @fuzzy:假设要编译的第一个utility.cpp 定义了命名空间foo_ns 下的所有内容,而要编译的第二个utilty.cpp 编译命名空间bar_ns 下的所有内容,编译器会覆盖utility.obj编译第二个 utility.cpp... 时,链接器启动时,.obj 文件中只有 bar_ns 可用。

标签: c++ visual-studio-2008 visual-c++ linker-errors visual-c++-2008


【解决方案1】:

右键单击两个/任一 .cpp 文件 > properties > C/C++ > Output Files > Object File Name > 设置自定义名称。例如如果两个文件在文件夹A 中命名为MyFile.cpp,另一个在文件夹B 中,则可以将输出设置为AMyFileBMyFile

或者,您也可以使用宏为对象名称添加直接父文件夹名称的前缀(即使用$(IntDir)\$(SafeParentName)$(SafeInputName))。如果这还不够(例如,您有A/B/MyFile.cppC/B/MyFile.cpp)并且您不介意将一些目标文件弄乱源代码树,您也可以使用$(InputDir)\,它将目标文件放在与源文件。

cpp 文件随后将被编译成两个不同的目标文件..

享受吧!

VS2010 更新: VS2010 中有更好的解决方案,请查看here。感谢n1ckcomment

顺便说一句,如果内容具有相同的名称,你是否使用不同的命名空间将它们分开?

namespace A { // in folder A
    class CMyFile {};
};

namespace B{ // in folder B
    class CMyFile {};
};

// client.cpp
#include "A/MyFile.h"
#include "B/MyFile.h"
int main() {
    A::CMyFile aMyFile;
    B::CMyFile bMyFile;
    return 0;
}

我不知道这是否重要,但对人类来说肯定更清楚:D

【讨论】:

  • 这是解决方案 - 但请注意,由于某种原因,.cpp 文件具有不同的名称,并且 .obj 文件会显着减慢编译/链接周期。我不知道为什么。
  • 应该工作并且应该是解决方案,但它对我不起作用。 VS 会创建两个 .obj 文件,但会尝试仅链接其中一个。
  • 我收回了 - 重新加载解决方案似乎使这项技术工作(就像它应该的那样)。 +1。出于某种原因,今天早上 VS 对我很敏感。
  • @afriza、AMyFile 和 BMyFile... 看起来像硬编码。是否有一个宏可以用来插入.cpp 的相对路径作为“.obj”路径的一部分?
  • @afriza: 是的,我猜 $(InputDir) 会在生死攸关的情况下工作,但在我的情况下这比“手动”做更糟糕,因为它会污染 src/ 目录很多的目标文件。无论如何,它已在 msvc2010 (stackoverflow.com/questions/3695174/…) 中修复,所以对我来说不是太大问题。
【解决方案2】:

您可以尝试将另一个项目添加到您的解决方案中,该项目将从模块的 .cpp .h 构建静态 mudule.lib 文件,然后将您的主项目与该库链接。它应该使VS在单独的目录中输出.obj文件,并且您应该可以毫无问题地链接。

【讨论】:

    【解决方案3】:

    您真的希望在同一个项目中有两个不同但名称相同的文件吗?

    【讨论】:

    • 当然。子文件夹中的 utility.hutility.cpp 添加特定于该文件夹中实现的功能的功能。
    • 如果您在构建中包含其他实用程序,您通常别无选择。
    【解决方案4】:

    最简单的方法是根据源目录将冲突的 .objs 放入不同的子文件夹(我在 2003 和 2008 中使用过这种技术)。

    例如:

    对于 src\gui\utils.cpp 将“对象文件名”设置为“.\Debug\gui/”并且 对于 src\database\utils.cpp 将其设置为“.\Debug\database/”。

    虽然我在发现冲突时手动执行此操作,但我可以想象为每个 .cpp 文件(或仅针对冲突文件)编写一个更新项目的脚本将是一项非常微不足道的任务。

    【讨论】:

      【解决方案5】:

      也许库(静态或动态)会对您的案例有所帮助。但是,如果在可执行文件或其他库中存在任何同名的公共符号,您仍然会遇到问题。

      【讨论】:

        【解决方案6】:

        我不知道VS的编译链。

        但是,每个 .cpp 首先被编译成一个 .obj 文件。链接步骤将它们合并在一起。

        将所有 .obj 文件放在同一个目录中是很常见的。因此,正如您所猜测的,在编译第二个时,会删除第一个。因此在编译过程中缺少一些符号。

        可能有一个选项(同样,我不使用 VS)将 .obj 保留在与 .cpp 文件相同的目录中。缺点是您的源代码树上有一些垃圾。

        我的个人意见是重构。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2010-12-26
          • 1970-01-01
          • 2018-09-14
          • 1970-01-01
          • 2013-12-30
          • 2013-02-04
          • 2020-12-10
          • 2021-04-16
          相关资源
          最近更新 更多