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

#import和#include在Objective-C中的区别是什么?在某些情况下你应该使用其中一个而不是另一个?一个被弃用了吗?

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

148857 次浏览

#include的工作原理就像C #include

#import跟踪哪些头文件已经被包含,如果一个头文件在编译单元中被导入多次,则该头文件将被忽略。这使得没有必要使用头保护。

底线是在Objective-C中使用#import,不要担心你的头文件会多次导入一些东西。

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

基本上,由您决定使用哪一种。我倾向于#import Objective-C内容(如类定义等)的头文件,#包含我需要的标准C内容。例如,我的一个源文件可能是这样的:

#import <Foundation/Foundation.h>


#include <asl.h>
#include <mach/mach.h>

#include它用来从另一个文件中获取“东西”到#include所使用的文件中。 例:< / p >

文件:main.cpp

#include "otherfile.h"


// some stuff here using otherfile.h objects,
// functions or classes declared inside

头保护用于每个头文件(*.h)的顶部,以防止包含同一个文件超过一次(如果发生这种情况,您将得到编译错误)。

文件:otherfile.h

#ifndef OTHERFILE
#define OTHERFILE


// declare functions, classes or objects here


#endif

即使你在代码中放入#include "otherfile.h" n次,其中的this也不会被重新声明。

如果你在.h文件中两次包含一个文件,编译器将会给出错误。 但是如果你#import一个文件多次,编译器就会忽略它

关于预处理器,似乎有很多困惑。

当编译器看到#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行只在第一次遇到时被命名文件的内容替换。之后的每一次都被忽略了。

我同意杰森的观点。

我这样做被抓了个现行:

#import <sys/time.h>  // to use gettimeofday() function
#import <time.h>      // to use time() function

对于GNU gcc,它一直抱怨time()函数是 没有定义。< / p >

然后我把#import改为#include,一切正常。

原因:

You #import <sys/time.h>:
,,, & lt; sys / time.h>只包含部分的<time.h>通过使用#定义

You #import <time.h>:
,,,没成功。即使只是一部分<时间。已包含,如
   就#import而言,该文件现在已经包含完全

底线:

C/ c++头文件通常包含其他包含文件的部分 所以对于C/ c++头文件,使用#include.
对于objc/objc++头文件,使用#import.

如果您熟悉c++和宏,那么

#import "Class.h"

类似于

{
#pragma once


#include "class.h"
}

这意味着当你的应用程序运行时,你的类只会被加载一次。

我知道这个帖子很旧…但在“现代”…通过clang的@import模块有一个更优秀的“include策略”-这经常被忽视。

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

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

@import Foundation;  //  Like #import <Foundation/Foundation.h>
@import ObjectiveC;  //  Like #import <objc/runtime.h>

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

要启用模块,在编译时在Xcode-中传递命令行标志-fmodulesCLANG_ENABLE_MODULES。如上所述…此策略避免ANY和ALL LDFLAGS。正如在,你可以删除任何“OTHER_LDFLAGS”设置,以及任何“链接”阶段..

enter image description here

我发现编译/启动时间“感觉”更迅速(或者可能,在“链接”时延迟更少?)..同时,也提供了一个很好的机会来清除现在多余的Project-Prefix。pch文件,以及相应的构建设置,GCC_INCREASE_PRECOMPILED_HEADER_SHARINGGCC_PRECOMPILE_PREFIX_HEADER,和GCC_PREFIX_HEADER,等等。

你可以为你自己的框架创建__abc,并以同样方便的方式包含它们。你可以看看我的ObjC-Clang-Modules github回购的一些例子,如何实现这样的奇迹。

在可能的情况下,我在我的一个.h文件中有一个全局变量导致了这个问题,我通过在它前面添加extern来解决它。

#include vs #import

历史:

#include => #import => Precompiled Headers .pch => @import Module(ObjC); => import Module(Swift)
< p > [预编译Headers .pch]
【@ import模块(ObjC);】
(导入模块(斯威夫特))
< / p >
#include + guard == #import

#include guard<一口> Wiki > < /晚餐 -宏保护,头保护或文件保护防止双包含preprocessor的头,这会减慢构建时间

#进口劣势

适用于文件作用域,这就是为什么我们的构建时间较慢的原因,因为编译器必须解析和编译与项目作用域中导入的.h文件相同数量的文件

[#import in .h or .m] . import in .h or .m