您通常不需要详细了解Obj文件的内部格式,因为它们是为您生成的。所有你需要知道的是,对于你创建的每一个类,编译器都会生成Obj文件,它是你的类的二进制字节码,适合于你编译的操作系统。然后,下一步 - 链接 - 将您的程序所需的所有类的目标文件放在一个EXE或DLL中(或其他任何非Windows OS-es的格式)。也可以是EXE +几个DLL,这取决于你的意愿。
最重要的是你分开你的类的接口(声明)和实现(定义)。
总是只放在你的类的头文件接口声明。没有别的 - 这里没有实现。避免使用自定义类型的成员变量,这些类型不是指针,因为对于它们来说,前向声明是不够的,你需要在头文件中包含其他头文件。如果你的标题包含了,那么设计就会有气味,并且会减慢构建过程。
类方法或其他函数的所有实现应该在CPP文件中。这将保证当有人包含您的头文件时,编译器生成的Obj文件将不再需要,并且您只能从CPP文件中包含其他文件。
但为什么要麻烦?答案是,如果你有这样的分隔,那么链接速度会更快,因为每个类都使用了每个Obj文件。另外,如果你改变了你的类,这将在下一次构建时改变其他一些对象文件。
如果你在头文件中包含了,这意味着当编译器为你的类生成Obj文件时,它应该首先为你的头文件中包含的其他类生成Obj文件,这可能需要其他Obj文件等等。甚至可能是循环依赖,然后你不能编译!或者如果你改变了你的类中的某些东西,那么编译器将需要重新生成许多其他的Obj文件,因为如果你没有分离,它们会在一段时间后变得非常紧密依赖。
我不认为看对象文件将有助于理解你提到的观点。思考“编译器需要知道如何为这个输入创建机器代码”这个问题可能更有用?例如,要将'A * a'传递给下一个函数,编译器不需要知道A是什么样子,而是调用'a-> foo()',它就是这样。从“A”派生,至少需要知道“A”的大小和所有方法签名。 – 2010-07-09 07:46:04
嗨克里斯托弗,我同意你的观点。事实上,这就是我想从哪里开始。但是,即使像“从A派生出来的东西,至少需要知道A的大小”对我来说也不是那么明显。为什么不能将A的大小知识推迟到说出运行时间,或者说在链接时间,而不是在创建目标文件时的编译时间。因此,我得出结论,我可能需要从不同的角度理解编译器在目标文件中放置什么信息。 – xyz 2010-07-09 07:54:45
我认为Stanley B Lippman的书:“C++内部对象模型”可以帮助你理解一些主题 – 2010-07-09 08:50:04