#import和#include在Objective-C中的区别是什么?在某些情况下你应该使用其中一个而不是另一个?一个被弃用了吗?
我正在阅读下面的教程:http://www.otierney.net/objective-c.html#preamble和它关于#import和#include的段落似乎自相矛盾,或者至少不清楚。
#include的工作原理就像C #include。
#include
#import跟踪哪些头文件已经被包含,如果一个头文件在编译单元中被导入多次,则该头文件将被忽略。这使得没有必要使用头保护。
#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也不会被重新声明。
关于预处理器,似乎有很多困惑。
当编译器看到#include时,它会用包含的文件的内容替换该行,不问任何问题。
因此,如果你有一个包含以下内容的文件a.h:
a.h
typedef int my_number;
和一个包含以下内容的文件b.c:
b.c
#include "a.h" #include "a.h"
文件b.c将在编译之前由预处理器翻译
typedef int my_number; typedef int my_number;
这将导致编译器错误,因为my_number类型定义了两次。尽管定义是相同的,但C语言不允许这样做。
my_number
由于头文件经常在多个地方使用,包括警卫通常在c中使用。
#ifndef _a_h_included_ #define _a_h_included_ typedef int my_number; #endif
b.c文件在预处理之后仍然会有两次头文件的全部内容。但是第二个实例将被忽略,因为_a_h_included_宏已经被定义了。
_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++和宏,那么
#import "Class.h"
类似于
{ #pragma once #include "class.h" }
这意味着当你的应用程序运行时,你的类只会被加载一次。
我知道这个帖子很旧…但在“现代”…通过clang的@import模块有一个更优秀的“include策略”-这经常被忽视。
@import
模块通过将文本预处理器包含模型替换为更健壮、更高效的语义模型,改进了对软件库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-中传递命令行标志-fmodules即CLANG_ENABLE_MODULES。如上所述…此策略避免ANY和ALL LDFLAGS。正如在,你可以删除任何“OTHER_LDFLAGS”设置,以及任何“链接”阶段..
Xcode
-fmodules
CLANG_ENABLE_MODULES
LDFLAGS
我发现编译/启动时间“感觉”更迅速(或者可能,在“链接”时延迟更少?)..同时,也提供了一个很好的机会来清除现在多余的Project-Prefix。pch文件,以及相应的构建设置,GCC_INCREASE_PRECOMPILED_HEADER_SHARING, GCC_PRECOMPILE_PREFIX_HEADER,和GCC_PREFIX_HEADER,等等。
GCC_INCREASE_PRECOMPILED_HEADER_SHARING
GCC_PRECOMPILE_PREFIX_HEADER
GCC_PREFIX_HEADER
你可以为你自己的框架创建__abc,并以同样方便的方式包含它们。你可以看看我的ObjC-Clang-Modules github回购的一些例子,如何实现这样的奇迹。
在可能的情况下,我在我的一个.h文件中有一个全局变量导致了这个问题,我通过在它前面添加extern来解决它。
.h
extern
#include vs #import
历史:
#include => #import => Precompiled Headers .pch => @import Module(ObjC); => import Module(Swift)
#include + guard == #import
#include guard<一口> Wiki > < /晚餐 -宏保护,头保护或文件保护防止双包含preprocessor的头,这会减慢构建时间
#include guard
preprocessor
#进口劣势
适用于文件作用域,这就是为什么我们的构建时间较慢的原因,因为编译器必须解析和编译与项目作用域中导入的.h文件相同数量的文件
[#import in .h or .m] . import in .h or .m
.m