繁体   English   中英

C / C ++项目的基本结构(头文件和cpp文件)

[英]Basic stucture of a C/C++ project (header files and cpp files)

这是一个脑死亡的新手问题,但这里有:

是什么决定了什么文件包含在C / C ++项目中?

我的理解是编译器从包含main()的文件开始,该文件将包含#include以获取包含#include到其他h文件的各种h文件,依此类推,直到项目中包含所有内容。

我的问题:

h文件和同名cpp文件之间有什么关系? 我的意思是,当然我理解代码方面他们需要彼此和cpp文件总是(几乎总是?)#include是h文件,但从编译器的角度来看,重要的是他们有相同的名称或者是这只是一个惯例? 我可以包含没有相应h文件的额外cpp文件吗?

此外,在构建和链接项目时,它如何知道构建目标文件的cpp / h文件? 它只是从cpp文件开始,其中包含“main()”并继续浏览#include,直到它拥有所需的一切并构建所有这些,或者它只构建用户在makefile或make中指定的所有内容IDE项目文件?

最后,当链接器最终出现并链接所有目标代码以生成可执行文件时,是否有特殊的顺序它会安排所有内容?

任何帮助,提示,解释赞赏..谢谢!

--R

网上的一点点狩猎会得到很多答案。 这里只有两个: http//www.psgd.org/paul/docs/cstyle/cstyle02.htm

http://www.cs.utexas.edu/~lavender/courses/EE360C/lectures/lecture-02.pdf

第二个非常好。

我还推荐c ++编程语言第3版。 关于文件组织有一个很棒的部分。

至于编译器的作用,最好在另一篇文章中解释。 简而言之,每个cpp文件都被编译成一个转换单元(目标代码),然后链接器将所有内容连接到最终的可执行文件中。

将文件视为分割代码的简单方法,使其更具可重用性和可维护性。

您可以轻松地将整个应用程序放在一个大的鸣笛源文件中,但是您可能会发现该文件会变得相当大,导致编译器抱怨它(或者至少花费很长时间来编译它)。

通常,您可以将应用程序的一部分(例如通用数据库访问层)放入单独的源文件(如db.cpp并使用其API创建db.h文件。 db.cpp并没有使用这个文件,因为它需要在db.cpp调用函数的所有其他文件使用它。 可以包含在db.cpp但它主要是发布有关db代码的信息。

至于环境如何计算编译/链接的东西:你倾向于有一个类型的项目(makefile,IDE项目文件等),它列出了你想要编译的所有程序(通常不是头文件)。

环境将编译它已被告知要生成目标文件的每个源文件 - 此过程的一部分是将包含的头文件合并到每个源文件中,以创建编译或转换单元 - 此单元基本上是源文件包含的头文件包含在#include所在的位置。

然后,环境将链接所有目标文件以形成可执行文件。 请记住,此过程存在变化,例如延迟(动态)链接。 请参阅此处以获取对此的描述。

头文件本质上是类的前向声明及其所有成员属性和函数,这基本上使您的类更可重用且更易于访问。 将其视为一个没有实现的接口,因此无论谁使用它都不必担心该特定类的源。 据我所知,相应的h文件和cpp文件需要具有相同的名称。 一个cpp文件不一定总是有一个相应的h文件,你可以把你所有的源都放在一个cpp文件中而没有任何h文件,只要一切都正确实现并且原型正确,一切都应该正常工作。

您的分析基本上是正确的...所有包含的文件都已扩展到位,并且生成的代码(翻译单元)被编译到对象,库或应用程序中。

尽管如此,任何非平凡的项目都依赖于其他库中定义的符号(变量,函数),即使只是用于语言或操作系统提供的malloc(),socket(),file(),write()等内容。标准库。 即使你不直接调用它们,也需要实现new和iostream之类的东西。

当您自己的项目变得更大时,您还需要将您的功能划分为不同的对象或库,因为这使得功能更易于重复使用,可独立测试,并且意味着在某些代码更改后您只能重新编译那些无效的对象。然后重新连接 - 这比重新编译整个项目中的每一段代码要快得多。

您的C ++编译器从翻译单元创建对象(可能有也可能没有额外的接口和代码来使它们成为库或应用程序) - 这是您提到的includes和cpp文件的连接 - 可能导入并将其与来自的符号组合在一起现有的静态库或您在编译器命令行中提到的其他对象。

对于每个独立对象,编译器需要能够告诉新代码如何访问和使用包含的符号; 头文件用于此目的,通告可用对象内容。

实现(cpp)文件应该几乎总是首先包含它们的头文件,因为如果它正在构建的对象内容与使用该对象的代码稍后期望的头文件广告内容之间存在某种差异,则编译器将抱怨。 对于某些事情 - 比如类,必须在指定成员函数实现之前看到类声明,并且假定客户端代码需要类声明,因此在标题中,实际上实现也需要包含标题。 (我说的cpp应该包括它的头首先是因为编译器会又抱怨如果头依赖于一些内容,它不包括本身。否则,如果说CPP包含的std :: string标题和标题上使用它,但是其他一些客户端代码尝试包含头而没有包含字符串,那么编译将失败)。

实现文件可能包含其他实现文件,但这不符合上述编译的一般划分,因此会使用于此约定的人感到困惑。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM