#import和#include在Objective-C中的区别是什么?在某些情况下你应该使用其中一个而不是另一个?一个被弃用了吗?
我正在阅读以下教程:http://www.otierney.net/objective-c.html#preamble,其中关于#import和#include的段落似乎自相矛盾,至少不清楚。
#import和#include在Objective-C中的区别是什么?在某些情况下你应该使用其中一个而不是另一个?一个被弃用了吗?
我正在阅读以下教程:http://www.otierney.net/objective-c.html#preamble,其中关于#import和#include的段落似乎自相矛盾,至少不清楚。
#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的文件中。 例:
文件: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,里面有这样的内容:
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()函数是 没有定义。
然后我把#import改为#include,一切正常。
原因:
#import <sys/time.h>: <sys/time.h>通过使用#定义只包含<time.h>的一部分
#import <time.h>: 没有去。尽管<time.h>只包含了一部分,as 就#import而言,该文件现在已经完全包含在内。
底线:
C/ c++头文件通常包含其他包含文件的部分。 所以对于C/ c++头文件,使用#include。 对于objc/objc++头文件,使用#import。
如果您熟悉c++和宏,那么
#import "Class.h"
类似于
{
#pragma once
#include "class.h"
}
这意味着当你的应用程序运行时,你的类只会被加载一次。
我知道这个帖子很旧…但在“现代”…通过clang的@import模块有一个更优秀的“包含策略”-这经常被忽视。
模块通过将文本预处理器包含模型替换为更健壮、更高效的语义模型,改进了对软件库API的访问。从用户的角度来看,代码看起来只是略有不同,因为使用了import声明而不是#include预处理器指令:
@import Darwin; // Like including all of /usr/include. @see /usr/include/module.map
or
@import Foundation; // Like #import <Foundation/Foundation.h>
@import ObjectiveC; // Like #import <objc/runtime.h>
However, this module import behaves quite differently from the corresponding #include: when the compiler sees the module import above, it loads a binary representation of the module and makes its API available to the application directly. Preprocessor definitions that precede the import declaration have no impact on the API provided... because the module itself was compiled as a separate, standalone module. Additionally, any linker flags required to use the module will automatically be provided when the module is imported. This semantic import model addresses many of the problems of the preprocessor inclusion model.
要启用模块,在编译时传递命令行标志-fmodules,也就是Xcode中的CLANG_ENABLE_MODULES。如上所述…该策略避免了任何和所有ldflag。正如在,你可以删除任何“OTHER_LDFLAGS”设置,以及任何“链接”阶段..
我发现编译/启动时间“感觉”更迅速(或者可能,在“链接”时延迟更少?)..同时,也提供了一个很好的机会来清除现在多余的Project-Prefix。pch文件,以及相应的构建设置,gcc_incree_precompiled_header_sharing, GCC_PRECOMPILE_PREFIX_HEADER, GCC_PREFIX_HEADER等。
此外,虽然没有良好的文档…映射到您自己的框架,并以同样方便的方式包含它们。你可以看看我的ObjC-Clang-Modules github回购的一些例子,如何实现这样的奇迹。
#include vs #import预处理器指令
历史:
#include -> #import ->[预编译Headers .pch] -> [@import Module(ObjC);] -> [import Module(Swift)]
#import是#include的下一代,它解决了当前.h文件的双重包含和递归包含问题。只是当前文件中包含的。h主体的单一副本
#import == #include + guard
守卫长这样
#ifndef <some_unique_name>
#define <some_unique_name>
<header_body>
#endif
#include guardWiki(宏保护,头保护,文件保护)-防止预处理器包含多个头,这会减慢构建时间
#include和#import使用了一种复制/粘贴机制——递归地复制.h文件主体(除了#include, #import指令之外的所有内容)。这意味着结果文件将不包含#include, #import指令)
如果选择。m文件Product -> Perform Action ->预处理“。m”,可以检查结果。
# include示例
//A.h
@interface A : NSObject
- (int)startA;
@end
//ViewController.h
#include "A.h"
ViewController。M预处理后
@interface A : NSObject
- (int)startA;
@end
@interface ViewController : UIViewController
@end
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
}
@end
双重包含示例
//A.h
@interface A : NSObject //Build time error: Duplicate interface definition for class 'A'
@end
//B.h
#include "A.h"
//C.h
#include "A.h"
//#import "A.h" to solve
#include "B.h"
递归包含示例
//A.h
#include "B.h" //Build time error: #include nested too deeply
//#import "B.h" to fix it
@interface B : NSObject //Build time error: Duplicate interface definition for class 'A'
@end
//B.h
#include "A.h" //Build time error: #include nested too deeply
//#import "A.h" to fix it
@interface B : NSObject //Build time error: Duplicate interface definition for class 'B'
@end
[#import in .h or .m]