【问题标题】:Is it possible to have identically named source files in one visual studio c++ project?是否可以在一个 Visual Studio C++ 项目中拥有同名的源文件?
【发布时间】:2010-01-04 12:07:33
【问题描述】:

我正在为我正在学习的一门 C++ 课程开发一个静态库项目。老师坚持我们每个源文件只定义一个函数,将属于同一类的文件/函数分组到每个类的子目录中。这会产生如下结构:

MyClass
    \MyClass.cc (constructor)
    \functionForMyClass.cc
    \anotherFunctionForMyClass.cc 
OtherClass
    \OtherClass.cc (constructor)

我不想讨论这是否是好的做法,因为我只是不得不以这种方式组织我的项目。

我在 Visual Studio 2008 中工作,在两个类中使用同名函数(以​​及文件名)时不知何故出现了奇怪的链接错误。这似乎是由于 Visual Studio 将所有 .obj 文件(每个源文件一个)放在一个中间目录中,在编译同名源文件时覆盖了之前生成的目标文件。

这可以通过根据输入文件的相对路径将目标文件放在子目录中来解决。 Visual Studio 允许配置它生成的目标文件的名称并在其中使用宏,但似乎没有“输入文件的相对路径”的宏。

那么,有什么方法可以让它工作吗?如果不是,每个班级使用一个项目是最好的解决方法吗?

【问题讨论】:

  • 你确定 VS 会覆盖之前生成的目标文件吗?你得到什么链接错误?
  • @Serge:事实上,它实际上似乎是在编译第一个源文件后跳过编译。我在定义缺失函数的文件中抛出了一个#error,并且没有出现编译错误。将文件重命名为不同的名称会导致文件被编译。无论如何:编译项目后只有一个目标文件。
  • 我在这里能看到的唯一好处是,你正在努力了解 VS2008 的真正工作原理,这样当别人把自己画到角落里时,你就会知道去哪里看 - 一个非常黑暗的角落。
  • @TC:我问的原因是我在 VS2005 的不同目录中创建了一个包含两个同名源文件的测试项目,它构建得很好。 VS 在第二个对象文件名的末尾添加一个“1”(例如“test.obj”和“test1.obj”)。所以也许问题不在你认为的地方。
  • @Serge:这是VS2008中引入的问题

标签: c++ visual-studio macros


【解决方案1】:

您是对的,默认情况下,所有目标文件都放在同一个目录中,并且它们的文件名基于源文件名。我能想到的唯一解决方案是在此处更改冲突文件的输出文件路径:

Project Properties-C/C++-Output Files-Object File Name http://img37.imageshack.us/img37/3695/outputfile.png

PS。听起来讲师有一个蹩脚的(可能是讲师自己写的)自动代码验证器,它强加了这个限制。要获得额外分数,请提供重写解析器,使其适用于正常/理智/非奇怪的项目布局。

【讨论】:

  • 具体来说,Igor 说您需要右键单击每个可能存在冲突的文件并更改其属性。
  • 看看stackoverflow.com/a/3731577/17349 - 看来你可以指定一个项目范围的设置来解决这个问题
【解决方案2】:

真正的答案:

改变

C/C++ => 输出文件 => 输出文件名

$(IntDir)/%(RelativeDir)/

每个 .obj 文件都将在一个子文件夹中创建,因此它不会覆盖之前的链接。

【讨论】:

  • 赞成,这就是我在谷歌上搜索的目的。我做了一段时间,但忘记了我到底做了什么......
【解决方案3】:

我想不出任何方法来伪造项目设置以让 VStudio 自动将中间文件拆分到单独的文件夹中。

你有几个机会 -

  1. 将类名构建到每个文件名中。大多数 IDE 仅在选项卡视图中显示文件名,因此如果您在不同的类中有多个具有相同名称的方法,如果文件名不包括类名和方法名,则很难区分它们.这就是为什么我认为你老师的建议很疯狂的原因。我还没有看到任何提倡这种方法的编程风格指南。此外,它直接违背了各种工具的工作方式——如果您使用 Visual Studio 创建一个类,它会创建一个 cpp 文件和一个头文件,并自动将每个新函数附加到单个 cpp 文件中。

  2. 您可以为每个类创建一个静态库。在静态库中链接时,obj 文件都打包在 .lib 中,因此冲突不再是问题。

  3. 将 comp-sci 课程切换到不是由疯狂工作教授的课程。说真的,这家伙完全脱离了行业最佳实践,并试图将他们自己的奇怪想法强加给他们的学生:这些想法一旦离开教学环境就必须忘却。

【讨论】:

  • +1 特别是第 3 点。滚出那门课程,它弊大于利。
  • 除非是以后好东西的前提。为了一个有价值的长期目标而遭受一定程度的疯狂并不是完全无用的经验;-)
  • 我(TS)在这里和史蒂夫在一起。我是自学 c++ 的,这门课程和它的老师无疑大大提高了我的能力。疯狂是有方法的:这种组织方式确实有好处(编译时间,整洁的小源文件)也有缺点。我只是做我在任何课程中所做的事情:保持批判性,不要盲目采纳建议的所有内容,并选择我认为有用的部分:)
  • 有时即使是最非正统的方法也会给我们上宝贵的一课——如何做事。
【解决方案4】:

您还可以在其属性中更改每个文件的输出文件名。只需确保使用不同的名称即可。

【讨论】:

    【解决方案5】:

    你可以使用文件名中的类名来消除歧义吗?我想你可能有

    我的班级 \MyClass.cc(构造函数) \function1_MyClass.cc \function2_MyClass.cc

    这意味着每个文件都有一个足够独特的名称来解决问题。这是一个可以接受的策略吗?

    【讨论】:

      【解决方案6】:

      您可能可以安排项目的属性,将目标文件放入每个源文件文件夹下方的文件夹中。一旦项目有了这个属性,那么每个源文件都应该继承这个属性。 (但如果您已经按照 Igor 的建议进行了实验,那么您可能需要通过属性将它们重置回父级)。

      查看帮助文件后,我认为您应该转到项目属性/C C++/Outpuf Files/Object File Name: 并输入$(InputDir)(没有尾部反斜杠)。然后,每个源文件都应继承此属性,并且您的 .obj 文件应分开。

      在进行任何更改之前,您可能需要先发送Clean Solution

      【讨论】:

        【解决方案7】:
        • 重命名目标文件会起作用,但会很痛苦,而且会减慢编译/链接周期。我一直不明白为什么,但如果目标文件没有默认名称,这似乎会让 Visual Studio 感到困惑。

        • 你可以在函数名前加上类名;例如myclass-ctor.cc、myclass-function1.cc 等

        • 每个类可以有一个 .cc 文件,其中 #include 各个函数文件。在这种情况下,您需要防止 #included 文件被单独编译(重命名它们的扩展名或将 Properties->Exclude From Build 设置为 'Yes')。

        出于好奇,您的老师希望您将免费功能放在哪里,例如通常可能属于匿名命名空间的本地辅助函数?

        如果不是,为每个班级使用一个项目是最好的解决方法吗?

        不是一个好主意 - 除了您最终不会得到一个静态库(没有更多的诡计)之外,您的链接时间可能会增加并且它会隐藏一个 来自优化器的大量相关信息。

        另一方面;如果这门课程实际上是关于 C++ 而不是 OO 编程,那么做你需要通过的,但要听从老师的建议。

        【讨论】:

          【解决方案8】:

          您不必将它们放在不同的翻译单元中...为什么不将每个函数放在 .h 中,并将它们全部包含在每个类的一个 .cc 中?这很可能会从编译器中得到更好的输出。

          我想问为什么老师也坚持这种奇怪的结构,应该解释一下它背后的原因。我知道你没有问我们,所以我就说这么多。

          【讨论】:

          • 告诉我如何将两个成员函数 declarations 放入单独的头文件中...... (-1)
          • 问题希望类(和成员)声明在一个单独的头文件中,每个成员函数定义在一个单独的源文件中。这可以通过为每个 #included 在单个源文件中的函数定义创建一个单独的文件来实现。 #included 文件不应单独编译。
          【解决方案9】:

          在 Visual Studio 2010 中,我设置

              Properties -> C/C++ -> Output Files -> Output File Name
          

              V:\%(Directory)$(PlatformName)_$(ConfigurationName)_%(Filename).obj
          

          假设项目位于驱动器V 上,则 OBJ 文件最终位于源旁边(尚不知道是否有宏)。

          顺便说一句:$(InputDir) 指的是解决方案/项目目录,在另一个目录会导致同样的问题。

          【讨论】:

            猜你喜欢
            • 2011-12-15
            • 1970-01-01
            • 2012-12-31
            • 1970-01-01
            • 2011-05-13
            • 2015-12-09
            • 1970-01-01
            • 2023-04-07
            • 1970-01-01
            相关资源
            最近更新 更多