当前位置:  开发笔记 > 编程语言 > 正文

Objective-C中的#import和#include有什么区别?

如何解决《Objective-C中的#import和#include有什么区别?》经验,为你挑选了5个好方法。

在Objective-C中#import和#include之间有什么区别,有时候你应该使用一个而不是另一个吗?一个被弃用了吗?

我正在阅读以下教程:http://www.otierney.net/objective-c.html#preamble及其关于#import和#include的段落似乎自相矛盾或者至少不清楚.



1> Sven..:

关于预处理器似乎有很多混乱.

当编译器看到#include它用所包含文件的内容替换该行时,编译器会做什么,没有问题.

所以如果你有一个a.h包含这个内容的文件:

typedef int my_number;

b.c包含此内容的文件:

#include "a.h"
#include "a.h"

b.c在编译之前,预处理器将翻译该文件

typedef int my_number;
typedef int my_number;

这将导致编译器错误,因为类型my_number定义了两次.即使定义相同,C语言也不允许这样做.

由于头部经常在多个地方使用包括警卫通常在C.使用这看起来是这样的:

 #ifndef _a_h_included_
 #define _a_h_included_

 typedef int my_number;

 #endif

b.c在预处理之后,文件仍然会将标题的全部内容放入其中两次.但是第二个实例将被忽略,因为宏_a_h_included_已经被定义了.

这非常有效,但有两个缺点.首先必须编写包含警戒,并且每个标题中的宏名称必须不同.其次,编译器仍然需要查找头文件并按原样读取它.

Objective-C有#import预处理器指令(它也可以用于C和C++代码以及一些编译器和选项).这几乎#include与之相同,但它也在内部记录了哪些文件已被包含在内.该#import行仅在遇到第一次时被命名文件的内容替换.之后每次都被忽略了.


在7000行模板头文件中将4`#include`s更改为`#import`s后,在编译和XCode intellisense响应性方面有显着的性能提升.(我不认为我在想象)
这是比接受的答案更好的答案.@Guill,你应该改变接受的答案.

2> Jason Coco..:

#import指令作为#include的改进版本添加到Objective-C中.然而,它是否得到改善仍然是一个争论的问题.#import确保文件只被包含一次,这样你就不会遇到递归包含问题.但是,大多数体面的头文件都可以保护自己不受此影响,所以它并没有那么大的好处.

基本上,由您决定要使用哪个.我倾向于#import标头用于Objective-C事物(比如类定义等)和#include标准C我需要的东西.例如,我的一个源文件可能如下所示:

#import 

#include 
#include 


即使头文件包含包含保护,如果使用#include,在编译期间仍会有性能损失 - 编译器必须打开每个头文件以注意包含保护.
@dave - #import是预处理器的Objective-C添加.GCC也支持它在C和C++源文件中,尽管他们官方建议不要在C或C++中使用它,而是支持便携式传统的标头保护.但是,所有Objective-C预处理器都必须包含#import.
标题后卫是你添加到顶部的地方:`#ifndef myheader #define myheader` ...后跟标题代码......`#endif`
我认为#import实际上是GCC的补充,而不是Objective-C.只要用GCC(或Clang)编译,就可以在非ObjC语言中使用它
标头保护是一个预处理器指令,可确保标头仅在源文件中包含一次.
在一个不错的编译器上,include guard不会在编译时花费.如果要使用头文件,则需要包含一次头文件.当它包含在内时,编译器将检测到头部保护.并记住它.在同一文件的第二个#include上,编译器知道头文件保护,甚至不查看该文件.
这不是标准与非标准; 它是语言与语言,一种是另一种意图.如果您正在使用Objective-C**和**,您打算*包含Objective-C标头*,请使用#import.如果您正在使用C,C++**或**正在使用Objective-C并且只想在另一个文件中内联一个文件,请使用#include.
什么是头球卫士?
所以官方的建议是避免使用更新,更简单,更好的东西,以保持与旧版本的兼容性,这些东西可以很容易地更新以支持新关键字?那是胡说八道.有人需要引进一些新官员.
@aroth:这不是关于新的与旧的.这是关于标准与非标准的关系.
@Chuck-也许吧。但是,我认为,一个不会发展的标准,推荐过时,笨拙和过时的做事方式,并不是很有价值。尤其是当工具的功能不断发展时,甚至在“所有的Objective-C预处理程序都必须包含#import”时以及当我们在Objective-C项目的上下文中讨论代码时,其发展都是如此。

3> 小智..:

我同意杰森的观点.

我抓到了这样做:

#import   // to use gettimeofday() function
#import       // to use time() function

对于GNU gcc,它一直抱怨没有定义time()函数.

然后我将#import改为#include,一切顺利.

原因:

#import :
    仅包含一部分,使用#defines

你#import :
    不行.尽管只包含的一部分,但
    就#import而言,该文件现已完全包含在内.

底线:

C/C++传统上标头包括部件的其他包含文件.
因此,对于C/C++标头,请使用#include.
对于objc/objc ++标头,请使用#import.



4> Ferruccio..:

#include像C一样工作#include.

#import跟踪已包含哪些标头,如果在编译单元中多次导入标头,则会忽略这些标头.这使得不必使用标题保护.

底线只是#import在Objective-C中使用,如果您的标题最终导入不止一次,请不要担心.


假装我不熟悉C#include(主要是因为我不是),#include和#import之间的主要区别是什么?另外,你能告诉我头盔是什么吗?

5> Alex Gray..:

我知道这个线程很老......但是在"现代"......通过clang的@import模块有一个更优越的"包含策略" - 这是经常被忽视的..

模块通过用更健壮,更有效的语义模型替换文本预处理器包含模型来改进对软件库API的访问.从用户的角度来看,代码看起来只是略有不同,因为一个使用导入声明而不是#include预处理器指令:

@import Darwin; // Like including all of /usr/include. @see /usr/include/module.map

要么

@import Foundation;  //  Like #import 
@import ObjectiveC;  //  Like #import 

但是,此模块导入的行为与相应的#include完全不同:当编译器看到上面的模块导入时,它会加载模块的二进制表示,并使其API直接可供应用程序使用.导入声明之前的预处理程序定义对提供的API没有影响...因为模块本身被编译为单独的独立模块.此外,导入模块时将自动提供使用该模块所需的任何链接器标志.此语义导入模型解决了预处理器包含模型的许多问题.

要启用模块,传递命令行标志-fmodules又名CLANG_ENABLE_MODULESXcode-在编译时.如上所述..这种策略可以避免任何和所有LDFLAGS.在中,您可以删除任何"OTHER_LDFLAGS"设置,以及任何"链接"阶段.

在此输入图像描述

我发现编译/启动时间"感觉"更加快速(或者可能,"链接"时只有较少的延迟?)..而且,提供了清除现在无关的Project-Prefix.pch文件的绝佳机会,以及相应的构建设置GCC_INCREASE_PRECOMPILED_HEADER_SHARING,GCC_PRECOMPILE_PREFIX_HEADER以及GCC_PREFIX_HEADER

此外,虽然没有详细记录......您可以module.map为自己的框架创建s并以相同的方式包含它们. 你可以看看我的ObjC-Clang-Modules github repo,了解如何实现这些奇迹的一些例子.

推荐阅读
wangtao
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有