C++ 为什么包含头文件而不包含源文件?

C++ 为什么包含头文件而不包含源文件?,c++,visual-studio-code,C++,Visual Studio Code,我见过类似的问题,但它们对我的猿脑来说仍然没有意义 这里有一个例子。如果我在名为Bob.h的头文件中声明了一个函数:void PrintSomething()

我见过类似的问题,但它们对我的猿脑来说仍然没有意义


这里有一个例子。如果我在名为
Bob.h
的头文件中声明了一个函数:
void PrintSomething().cpp
文件中,我说:
void MyClass::PrintSomething(){std::cout当您包含
Bob.h
时,编译器就拥有了它需要知道的一切
PrintSomething()
,它只需要函数声明。
Frank.cpp
不需要知道定义
PrintSomething()
Bob.cpp

你所有的
cpp
文件都会输出由编译器生成的目标文件。这些文件本身没有多大作用,直到它们粘在一起,这是链接器的责任

链接器获取所有对象文件,并填充缺少的部分:

链接器对话:

嘿,我看到Frank.obj使用了
PrintSomething()
,我看不见 它的定义在该对象文件中

让我们检查其他对象文件

检查
Bob.obj
后,我可以看到它包含一个可用的
PrintSomething()
的定义,让我们使用它

这当然是简化的,但简言之,链接器就是这么做的

完成后,您将获得可用的可执行文件



最重要的是,如果我现在在Frank.cpp文件中说:
void MyClass::PrintSomething(){std::cout这里的关键概念是单独编译。您将项目划分为一组实现或多或少独立的东西的源文件,将这些源文件编译为目标文件,并链接目标文件和任何附加库(包括标准库)创建可执行文件。对于大型项目,编译所有源文件可能需要很长时间(有时以小时为单位)。第一次构建应用程序时,您必须这样做。但在那之后,如果您只更改了一个源文件,则只需重新编译该源文件,然后再次链接,即您第一次创建的对象文件。这通常可以节省大量时间。如果您有一个大型源文件(即,
#包含
s所有其他源文件的源文件),您没有这个选项——每次都必须重新编译整个文件。

“当我只包含了.h文件,而该文件没有说明“Hello”,只是一个声明时,它如何打印添加到.cpp文件中的“Hello”这就是链接器的工作。“我也看过编译过程和链接过程”仔细看看链接。“它会打印“你好”还是“再见”?”我敢肯定,如果你有两个相同函数的定义,你会得到一个链接器错误。但是,链接器对你的函数所做的工作与对库函数所做的工作是一样的。如果没有单独的链接器,编译你的程序会非常慢,因为系统头文件必须包含所有函数的完整定义l库函数和编译器必须为您对代码所做的每一次更改重新优化整个库。避免这一点是将多个编译单元链接在一起的要点。此外,还可以包括其他源单元,这样做被称为“统一构建”。这里的讨论:绝对漂亮的解释“Linker Talk”是我可以处理的一个层次,它是如何工作的,所以perfecto lmao。