【发布时间】:2010-10-01 04:18:04
【问题描述】:
Objective-C 中的#import 和#include 之间有什么区别?在某些情况下您应该使用其中一个而不是另一个?是否已弃用?
我正在阅读以下教程:http://www.otierney.net/objective-c.html#preamble 及其关于#import 和#include 的段落似乎自相矛盾,或者至少不清楚。
【问题讨论】:
标签: objective-c import include
Objective-C 中的#import 和#include 之间有什么区别?在某些情况下您应该使用其中一个而不是另一个?是否已弃用?
我正在阅读以下教程:http://www.otierney.net/objective-c.html#preamble 及其关于#import 和#include 的段落似乎自相矛盾,或者至少不清楚。
【问题讨论】:
标签: objective-c import include
#include 与 #import
历史:
#include => #import => Precompiled Headers .pch => @import Module(ObjC); => import Module(Swift)
[Precompiled Headers .pch]
[@import Module(ObjC);]
[import Module(Swift)]
#include + guard == #import
#include guardWiki - 宏保护、标头保护或文件保护可防止通过 preprocessor 双重包含标头,这会减慢构建时间
#import 劣势
适用于文件范围,这就是我们构建时间缓慢的原因,因为编译器必须解析和编译与项目范围中导入的 .h 文件一样多的次数
【讨论】:
在可能的情况下,我的一个.h 文件中有一个导致问题的全局变量,我通过在它前面添加extern 来解决它。
【讨论】:
#import 指令作为#include 的改进版本添加到Objective-C。然而,它是否得到改进仍然是一个争论的问题。 #import 确保文件只包含一次,这样您就不会遇到递归包含的问题。但是,无论如何,大多数体面的头文件都会保护自己免受这种情况的影响,因此它并没有太大的好处。
基本上,由您决定要使用哪个。我倾向于为 Objective-C 的东西(如类定义等)和 #include 我需要的标准 C 东西 #import 标头。例如,我的一个源文件可能如下所示:
#import <Foundation/Foundation.h>
#include <asl.h>
#include <mach/mach.h>
【讨论】:
#ifndef myheader #define myheader ... 后跟标题代码... #endif
我知道这个帖子很老了......但在“现代”......通过clang's @import modules 有一个非常优越的“包含策略” - 这是经常被忽视的......
模块通过将文本预处理器包含模型替换为更强大、更高效的语义模型来改进对软件库 API 的访问。从用户的角度来看,代码看起来只是略有不同,因为使用的是导入声明而不是#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 aka CLANG_ENABLE_MODULES。如上所述.. 这种策略避免了任何和所有LDFLAGS。如在,您可以删除任何“OTHER_LDFLAGS”设置,以及任何“链接”阶段..
我发现编译/启动时间“感觉”快得多(或者可能,“链接”时延迟更少?)..而且,提供了清除现在无关的 Project-Prefix.pch 的绝佳机会文件,以及相应的构建设置,GCC_INCREASE_PRECOMPILED_HEADER_SHARING、GCC_PRECOMPILE_PREFIX_HEADER 和 GCC_PREFIX_HEADER 等。
此外,虽然没有很好的记录……您可以为自己的框架创建module.maps,并以同样方便的方式包含它们。 You can take a look at my ObjC-Clang-Modules github repo for some examples of how to implement such miracles.
【讨论】:
我同意杰森的观点。
我被抓到这样做了:
#import <sys/time.h> // to use gettimeofday() function
#import <time.h> // to use time() function
对于 GNU gcc,它一直抱怨 time() 函数 未定义。
然后我将#import 更改为#include,一切正常。
原因:
你#import
你#import
不去。尽管只有
就 #import 而言,该文件现在已完全包含在内。
底线:
C/C++ 标头通常包含其他包含文件的部分。
因此,对于 C/C++ 头文件,请使用 #include。
对于 objc/objc++ 头文件,使用#import。
【讨论】:
如果你熟悉 C++ 和宏,那么
#import "Class.h"
类似于
{
#pragma once
#include "class.h"
}
这意味着当你的应用运行时你的类只会被加载一次。
【讨论】:
#pragma once 放置在包含文件中,而不是执行包含的文件中。 -1 。
#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 次放在你的代码里,它里面的这个也不会被重新声明。
【讨论】:
似乎有很多关于预处理器的混淆。
编译器在看到#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 行仅在第一次遇到时被命名文件的内容替换。之后每次都会被忽略。
【讨论】:
#includes 更改为 #imports 后,在编译和 XCode 智能感知响应方面有明显的性能提升。 (我不认为我在想象)
如果你在 .h 文件中 #include 一个文件两次,编译器就会报错。 但是如果你多次#import 一个文件,编译器会忽略它。
【讨论】:
#include同一个文件两次不会导致错误。
#include 只是一种复制粘贴机制。多次故意使用 #include 而不包含保护,例如“X 宏”。
#include 实现一种模板的C 代码。他们做了一个#define,包含了一个标题#undefd,并重做了#define,第二次包含了相同的标题。这导致代码被参数化、有效并包含两次,因为定义的值不同。所以使用#include 是有好处的,但是如果你使用像 C++ 或 ObjC 这样的现代语言,你通常不需要这个。
#include 与 C 中的 #include 一样工作。
#import 跟踪已包含哪些标头,如果在编译单元中多次导入标头,则将其忽略。这使得没有必要使用标题保护。
最重要的是在 Objective-C 中使用 #import,如果您的标头多次导入某些内容,请不要担心。
【讨论】: