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

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

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

#import指令作为#include的改进版本添加到Objective-C中。 然而,是否有所改善仍然是一个争议问题。 #import确保一个文件只包含一次,所以你永远不会有recursion包含的问题。 但是,大多数体面的头文件无论如何保护自己,所以它不是一个真正的好处。

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

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

似乎对预处理器有很多困惑。

当编译器看到一个#include ,它会用所包含的文件的内容replace那一行,而不会问任何问题。

所以如果你有这个内容的文件ah

 typedef int my_number; 

和一个文件bc与这个内容:

 #include "ah" #include "ah" 

文件bc将被编译前的预处理器翻译为

 typedef int my_number; typedef int my_number; 

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

由于标题经常用于多个地方,因此通常在C中使用警卫 。看起来像这样:

  #ifndef _a_h_included_ #define _a_h_included_ typedef int my_number; #endif 

文件bc在进行预处理之后,仍然会将头中的全部内容放入其中。 但是第二个实例会被忽略,因为macros_a_h_included_已经被定义了。

这工作得很好,但有两个缺点。 首先,必须写入包括卫兵,并且每个头文件中的macros名称必须是不同的。 其次,编译器仍然需要查找头文件,并按照包含的顺序阅读它。

Objective-C具有#import预处理器指令(它也可用于带有一些编译器和选项的C和C ++代码)。 这和#include几乎一样,但是它也在内部注意到哪个文件已经被包含了。 第一次遇到时, #import行只被replace为指定文件的内容。 每一次之后,它都被忽略了。

我同意杰森。

我被抓到了这样做:

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

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

于是我把#import改成了#include,一切就OK了。

原因:

你#import <sys / time.h>:
<sys / time.h>通过使用#defines只包含<time.h>的一部分

你#import <time.h>:
不行。 即使只有<time.h>的一部分已经被包含,如
就#import而言,该文件现在已经完全包含在内。

底线:

C / C ++头文件传统上包含其他包含文件的一部分。
所以对于C / C ++头文件,使用#include。
对于objc / objc ++头文件,使用#import。

#include作用就像C #include

#import跟踪哪些头文件已被包含,并且如果在编译单元中多次导入头文件,则会被忽略。 这使得没有必要使用标头警卫。

底线只是在Objective-C中使用#import ,如果您的头文件不止一次导入了某个东西,请不要担心。

我知道这个线程是旧的…但在“现代”..有一个远远优越的“包括战略”通过铛的@import模块 – 这是经常忽略..

通过用更健壮,更高效的语义模型replace文本预处理器包含模型,模块改进了对软件库API的访问。 从用户的angular度来看,代码只是略有不同,因为它使用的是一个导入声明而不是#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没有影响…因为模块本身被编译为独立的独立模块。 此外,导入模块时,将自动提供使用模块所需的任何链接器标志。 这个语义导入模型解决了预处理器包含模型的许多问题。

要启用模块,请在编译时CLANG_ENABLE_MODULES Xcode的命令行标志-fmodules aka CLANG_ENABLE_MODULES 。 如上所述,这个策略消除了任何和所有的LDFLAGS 。 如在,您可以删除任何“OTHER_LDFLAGS”设置,以及任何“链接”阶段..

在这里输入图像描述

我发现编译/启动时间“感觉”更快捷(或者可能只是在“链接”时没有什么滞后),而且还提供了清除现在无关的Project-Prefix.pch文件的好机会,相应的构build设置, GCC_INCREASE_PRECOMPILED_HEADER_SHARINGGCC_PRECOMPILE_PREFIX_HEADERGCC_PREFIX_HEADER

此外,虽然没有很好的文档…你可以创buildmodule.map s为自己的框架,并包括在同一个方便的方式。 你可以看看我的ObjC-Clang-Modules github回购的一些例子,了解如何实现这样的奇迹。

如果你熟悉C ++和macros,那么

 #import "Class.h" 

类似于

 { #pragma once #include "class.h" } 

这意味着你的类只会在应用运行时加载一次。

如果你在.h文件中包含两个文件比编译器会产生错误。 但是如果你多次input一个文件,编译器会忽略它。

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

#include它用来从另一个文件中获取“东西”到#include被使用的地方。例如:

在文件中: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”放入你的代码中,它里面的内容也不会被重新声明。