我有一个CarClass.h
文件,声明CarClass
然后我#import
将此CarClass.h
文件放入我的CarClass.m
文件中,然后我继续执行所有CarClass
方法。
最后,我的CarAPP.m
文件(其中包含main
)也#imports
CarClass.h
- 一切正常。
那里实际上没有问题: - )
但是,我不确定我理解为什么它有效 - 因为链接似乎有点偏离:如果CarAPP.m
仅导入CarClass.h
文件 - 而不导入CarClass.m
文件,然后从哪里获取或查看实现?
是这样的情况,一旦导入“.h”文件的“.m”文件被编译,那么两个文件(.h和.m)是排序永远链接的还是什么?
我只是不明白......
答案 0 :(得分:1)
编译过程分为不同的阶段,#import
指令在任何链接发生之前很久就被解释。
当您将代码文件(.c,.m)提供给编译器时,它将尝试从中生成代码对象文件(.o);也就是代码的二进制表示。此文件尚不可执行,因为它需要更多信息。特别是,它没有链接到任何其他文件。头文件,应该只包含声明而没有定义,通常不会得到自己的匹配.o文件。
在将所有代码文件转换为代码对象之后,编译器会将它们放在一起并调用链接器。链接器将解析所有外部引用,然后生成可执行文件。
重点是头文件告诉编译器存在某个的函数或方法。在编译的当前阶段,这足以生成目标文件:编译器只需要告知存在的内容,而不是定义的位置。只有当你真正链接时,你需要知道这一点。
由于所有代码对象文件都打包在一起,因此整个程序可以访问本身公开声明的所有内容。这就是为什么您不需要将CarAPP.m明确地“链接”到CarClass.m。
也可能误导编译器并在未在任何地方定义的头文件中声明函数。如果你在你的程序中使用它们,编译的第一阶段就会很好(没有语法错误,没有“未声明的函数”)但它会在链接时断开,因为链接器将无法找到不存在的函数
答案 1 :(得分:0)
当您有#import whatEver.h
时,预处理器会尝试在默认位置找到相应的文件。如果找到,它只会将whatEver.h
的内容粘贴到您使用#import whatEver.h
的相应源文件中。因此,要获得最终的可执行文件,源文件应该通过Pre-Process,Compile和Linker阶段。
当CarClass.h
中有CarAPP.m
时,链接器会在CarClass.h
中找到CarClass.m
的实现。严格地说,它是在CarClass.o
中找到定义。编译器很高兴只要有你使用的声明,并且链接器很满意,只要你打算使用声明的定义。
当您将CarClass.h
导入CarAPP.m
时,您要告诉链接器在CarClass.h
中找到CarClass.o
方法实现。因此,您的最终可执行文件是CarAPP.o
和CarClass.o
的组合。要了解有关如何完成编译和链接的更多信息,请Program Compilation。虽然链接是特定于C / C ++的,但它应该给你一个想法。