我在使用类时尝试了一些c ++代码,这个问题发生在我身上,这让我感到烦恼.
我创建了一个包含我的类定义的头文件和一个包含该实现的cpp文件.
如果我在不同的cpp文件中使用此类,为什么我要包含头文件而不是包含类实现的cpp文件?
如果我包含类实现文件,那么应该自动导入类头文件(因为我已经将头文件包含在实现文件中)?这不是更自然吗?
对不起,如果这是一个愚蠢的问题,我真的很有兴趣知道为什么大多数人包括.h而不是.cpp文件,当后者看起来更自然时(我知道python有点,也许这就是为什么它至少对我来说似乎很自然).它只是历史还是有关于计划组织的技术原因还是其他什么?
Dav*_*d Z 13
因为当您编译另一个文件时,C++实际上并不需要知道实现.它只需要知道每个函数的签名(它需要的参数和它返回的内容),每个类的名称,#defined 是什么宏,以及其他类似的"摘要"信息,以便它可以检查你是正确使用函数和类..cpp在链接器运行之前,不会将不同文件的内容放在一起.
例如,假设你有 foo.h
int foo(int a, float b);
Run Code Online (Sandbox Code Playgroud)
和 foo.cpp
#include "foo.h"
int foo(int a, float b) { /* implementation */ }
Run Code Online (Sandbox Code Playgroud)
和 bar.cpp
#include "foo.h"
int bar(void) {
int c = foo(1, 2.1);
}
Run Code Online (Sandbox Code Playgroud)
当你编译时foo.cpp,它就变成了foo.o,当你编译时bar.cpp,它就变成了bar.o.现在,在编译过程中,编译器需要检查的函数定义foo()中foo.cpp与函数的用法一致foo()的bar.cpp(即需要一个int和float并返回int).它的方式是让你在两个.cpp文件中包含相同的头文件,如果定义和用法都与头中的声明一致,那么它们必须彼此一致.
但是编译器实际上并没有包含foo()in 的实现bar.o.它只包含汇编语言指令call foo.因此,当它创建时bar.o,它不需要知道任何有关内容的信息foo.cpp.但是,当你进入链接阶段(在编译之后发生)时,链接器实际上确实需要知道实现foo(),因为它将在最终程序中包含该实现并call foo用a call 0x109d9829(或者它决定的任何内容)替换指令函数的内存地址foo()应该是).
需要注意的是链接程序不检查的实施foo()(在foo.o)配合使用的同意foo()(中bar.o) -例如,它不检查foo()获取调用与int和float参数!使用汇编语言进行这种检查很困难(至少比检查C++源代码更难),因此链接器依赖于知道编译器已经检查过它.这就是为什么你需要头文件来向编译器提供这些信息的原因.