提问者:小点点

为什么我们包含头文件而不包含源文件?


我见过类似的问题,但他们仍然没有意义,我的猿类大脑。

这里有一个例子。如果我在名为bob.h的头文件中声明了一个函数:void PrintSomething();并且在.cpp文件中声明了一个函数:void myclass::PrintSomething(){std::cout<<“hello”;}。我在另一个.cpp文件(例如frank.cpp)中看到过这样的人,它只包含bob.h头,它只有声明(里面没有代码),而不包含带有代码的.cpp。但令我震惊的是,当他们调用frank.cpp中的printSomething()函数时,它使用了bob.cpp中的代码并打印“hello”。怎么做?当我只包含了.h文件时,它如何打印在.cpp文件中添加的“hello”,而它只是一个声明,它对“hello”只字不提?我也看过编译过程和链接过程,但它就是不坚持。

如果我现在在我的frank.cpp文件中说:void myclass::printsomething(){std::cout<<“bye”;}并在我的main.cpp中包含bob.h文件,并调用printsomething()函数,那么它会打印“hello”或“bye”吗?电脑是灵媒还是什么?这个概念是我在C++学习过程中没有掌握的一件事。

提前道谢。


共1个答案

匿名用户

当您包含bob.h时,编译器就拥有了它需要知道的关于printSomething()的一切,它只需要函数的声明。frank.cpp不需要了解定义printSomething()bob.cpp

所有单独的cpp文件都输出编译器生成的对象文件。在它们被粘在一起之前,它们本身并没有什么作用,这是连接者的责任。

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

链接器对话:

嘿,我看到frank.obj使用了printSomething(),而我在该对象文件中看不到它的定义。

让我们检查其他对象文件。

在检查bob.obj时,我可以看到它包含了printSomething()的可用定义,让我们使用它。

这当然是简化的,但简而言之,这就是链接器的作用。

完成这些之后,您就得到了可用的可执行文件。

如果我现在在frank.cpp文件中说:void myclass::printsomething(){std::cout<<“bye”;}并在我的main.cpp中包含bob.h文件,并调用printsomething()函数,那么它会打印“hello”或“bye”吗?电脑是灵媒还是什么?

链接器会找到printsomething()的两个定义,并会发出一个错误,它无法知道哪个定义是要选择的正确定义。