C++如何在不编译cpp文件的情况下包含类头文件?

3
我们可以包含<iostream>,而且不关心它的cpp文件,但为什么我们不能对我们自己的类做同样的事情?
因此,如果我的项目使用了50个自定义类,我不仅需要有50个包含文件,还必须编译/链接50个cpp文件(并混乱地堆积在项目树中)。
问:是否有任何方法可以像使用标准库一样使用自定义头文件?
换句话说,有没有一种合法的方法,使我们不必将所有那些cpp文件添加到项目中。 我只想包括ClassSnake.hpp,它知道在哪里找到ClassSnake.cpp,后者链接到ClassVector.hpp,后者知道如何找到ClassVector.cpp......所有这些都是自动的,无需我明确地将这些cpp文件添加到我的项目树中。
编辑:我不太担心cpp文件重新编译的问题。我的问题在于必须“记住”哪个类内部链接到哪个其他类,以便我可以正确地将所有这些隐藏的cpp文件包含在项目树中...并且混乱了树形结构。

1
@dionadar,这不是解决问题的好方法。把所有实现都扔进头文件里,然后只是说“让它成为模板”并不能真正解决任何问题。 - Moo-Juice
@Moo-Juice 是的,每次你修改它时,所有内容都会重新编译。就像你包含的所有标准库头文件一样。 - danielschemmel
@dionadar,除了与标准库的比较不是一个很好的例子 :),它们很依赖于模板和头文件实现,这也是有充分理由的。然而,与此相反的是,OP只是不希望项目中的Cpps被重新编译(除非它们已被更改!)。我认为这听起来需要一个库。 - Moo-Juice
让我们就这个技术的有用性保持不同意见吧。然而,它是练习“使自定义标头像标准库一样工作”的有效解决方案 :) - danielschemmel
你的工具链应该只编译已修改或依赖于已修改头文件的cpp文件。通过将代码从头文件移入CPP文件中,可以降低重新编译cpp文件的风险。 - Thomas Matthews
显示剩余6条评论
6个回答

4

并不完全如此。

你所忽略的是,你的编译器工具链已经编译了头文件中所需的部分代码。

你的编译器(实际上是链接器)会在没有你指定的情况下隐式地将这些代码链接起来。

如果你想整理一下项目目录,可以创建其他项目作为主项目使用的代码库。


那么没有自动级联的方法吗?在First.hpp文件中放置一些内容,该内容查找其First.cpp和First.cpp文件包括second.hpp和third.hpp,这些文件知道如何找到它们各自的cpp文件...并自动向下传递? - Thomas An
这是你的构建系统需要解决的问题。看起来你正在使用Code::Blocks..它应该已经正确地处理了这个问题。 - Collin
我编译项目没有问题。问题在于必须在项目树中包含一堆cpp文件所造成的混乱。(每次都要记住哪个类链接到哪个其他类,以便手动提取那些cpp文件进行包含。) - Thomas An
这在C++编程中是一种事实。编译器需要编译你要使用的代码。你可以为项目创建子文件夹并组织你的代码。 - Collin

0

头文件通常不提供事物(函数、类)的实现,如果要使用它们,必须在某个地方实现它们。

当您包含自己的头文件时,您需要包含自己的源代码以提供实现。这很简单明了。

当您包含标准头文件(例如iostream)时,实现在您包含的库中(通过编译器/链接器选项隐式包含或显式包含)。


有没有愿意解释一下为什么要给这个投票点个踩?我很乐意修正或删除,但是未经解释就点踩并不是很有帮助。 - mah
可能只是回答这个问题的其他人之一。 - RandyGaul
@mah,我也遇到了同样的问题,已经标记了这个问题。 - Moo-Juice
我没有点踩,但这并没有回答问题...“有没有办法像使用标准库一样使用自定义头文件?”(尽管它确实描述了一些正在发挥作用的基本机制)。 - Chad Barth

0

作为对Collin答案的扩展,您可以将“共享”代码卸载到共享库中,然后在其他项目中引用头文件和lib文件。在链接器阶段,lib文件将只起作用,因为所有那些烦人的.cpp文件已经被编译。

如果这只是一个自包含的项目,没有其他共性,那么您就必须接受您必须提供实现的事实 :)


0

实际上,如果您有一个不错的构建过程,未更改的cpp文件将不会再次编译。它们只需要链接即可。如果您也不想这样做,您需要创建自己的库。这是可以做到的,只是需要更多的工作。

编辑:如果您想创建自己的库,此问题 可能会对您有所帮助。

因此,对于编辑后的问题的答案是:是的,您可以避免在项目中拥有所有这些cpp文件,但前提是您不想更改它们。在这种情况下,您只需创建一个静态或动态库,您只需要用于链接的符号即可。在这种情况下,您将创建另一个项目,将所有内容编译成这样的库。


谢谢!这是一个开始。我会研究动态库。感谢指引的方向 :-) - Thomas An

0
首先,如果您使用像make这样的系统,它会识别到.cpp文件没有更改,因此编译器不必重建对象文件。
您还可以创建自己的静态/共享库。如何执行此操作取决于平台。如果您选择这种方法,则只需要头文件和库即可。
请在Google上搜索如何为您特定的平台构建库。

-1

STL代码(如"iostream")由模板构成,只有在创建模板实例时才会生成代码。


实际上,您可以使用显式模板实例化从静态或共享库中生成模板的代码。编译器可能仍然会为您创建的实例生成代码,但通常在链接时会消除它。在 C++11 中,您可以将模板声明为 extern,以防止编译器实例化已经存在于某个库中的模板。 - Captain Obvlious
我的回答在问题的背景下是正确的。显式实例化不是一个问题,主要是因为你必须“显式地”使用它。 - Manuel del Castillo
抱歉,您的回答应该是一条评论。它没有回答OP实际提出的问题 - 如何像使用C++标准库一样使用头文件。虽然您对模板代码生成的描述还可以,但它并没有提供或建议任何类型的解决方案。 - Captain Obvlious

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接