#import
和#include
有什么区别?是否有时候应该使用其中一个而不是另一个?它们中的哪一个已被弃用了吗?#import
和#include
有什么区别?是否有时候应该使用其中一个而不是另一个?它们中的哪一个已被弃用了吗?关于预处理器似乎存在很多混淆。
当编译器遇到 #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语言通常会使用include guards。它的写法如下:
#ifndef _a_h_included_
#define _a_h_included_
typedef int my_number;
#endif
文件b.c在预处理后仍将包含整个头文件的内容两次。但是第二次实例会被忽略,因为宏_a_h_included_
已经被定义过了。这种方法非常有效,但有两个缺点。首先,必须编写include guards,并且每个头文件中的宏名称必须不同。其次,编译器仍需要查找头文件并读取它,就像它被包含多少次一样。Objective-C具有#import
预处理指令(某些编译器和选项也可用于C和C++代码)。这几乎与#include
相同,但它还在内部注明了已经被包含的文件。对于第一次遇到的命名文件,#import
行仅被替换为其内容。之后每次遇到它只会被忽略。#import <Foundation/Foundation.h>
#include <asl.h>
#include <mach/mach.h>
#ifndef myheader #define myheader
,然后再加上头文件的代码,最后以#endif
结束。这样做可以防止头文件被重复包含。 - Tim我同意Jason的观点。
我被抓到做了这件事:
#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>仅通过使用#define包含了<time.h>的一部分
您使用了#import <time.h>:
不行。尽管已经包含了<time.h>的部分内容,但是对于#import来说,该文件现在已经被完全包含了。
底线:
C/C++头文件传统上包含其他头文件的部分。
因此,对于C/C++头文件,请使用#include。
对于objc / objc ++头文件,请使用#import。
#include
和C语言的 #include
用法相同。
#import
可以跟踪已经包含的头文件,如果头文件在编译单元中被引用超过一次,则会被忽略。这使得使用头文件保护变得不必要。
总之,在Objective-C中只需要使用#import
,不用担心头文件会被重复引用。
@import
模块有一个更加优秀的“包含策略”,这常常被忽视了。
模块通过使用更加健壮、高效的语义模型替换文本预处理器包含模型,提高了对软件库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>
GCC_INCREASE_PRECOMPILED_HEADER_SHARING
, GCC_PRECOMPILE_PREFIX_HEADER
, and GCC_PREFIX_HEADER
, etc.module.map
文件,并以同样方便的方式包含它们。您可以查看我的ObjC-Clang-Modules GitHub存储库,以了解如何实现这些奇迹的一些示例。
#import "Class.h"
与...类似
{
#pragma once
#include "class.h"
}
#pragma once
应该放在被包含的文件中,而不是执行包含的文件中。对此给予 -1。 - herzbube如果在.h文件中两次#include同一个文件,则编译器会报错。 但是,如果多次#import同一个文件,则编译器会忽略它。
#include
两次不会导致错误。 - kennytm#include
只是一个复制和粘贴的机制。有意地多次使用#include
而没有包含保护,例如“X宏”。 - kennytm#include
实现一种模板的 C 代码。他们进行了 #define
,包含了一个头文件,然后 #undef
并重新进行了 #define
,第二次包含相同的头文件。这样可以使代码参数化、有效,并且被包含两次,因为定义的值是不同的。因此,使用 #include
有其优点,但如果你使用像 C++ 或 ObjC 这样的现代语言,通常不需要这样做。 - uliwitness#include
是用来从另一个文件中获取"东西"到使用#include
的文件中的。
例如:
在文件main.cpp中:
#include "otherfile.h"
// some stuff here using otherfile.h objects,
// functions or classes declared inside
头文件保护(Header guard)用于每个头文件(*.h)的顶部,以防止多次包含同一文件(如果发生这种情况,将会出现编译错误)。
在文件中:otherfile.h
#ifndef OTHERFILE
#define OTHERFILE
// declare functions, classes or objects here
#endif
#include
"otherfile.h",其中的内容也不会被重新声明。.h
文件中有一个全局变量导致了问题,通过在其前面添加 extern
来解决了这个问题。#include vs #import 预处理指令
历史:
#include -> #import -> [预编译头文件 .pch] -> [@import 模块(ObjC);] -> [import 模块(Swift)]
#import
是 #include
的下一代,解决了当前 .h 文件的 重复包含
和 递归包含
问题。在当前文件中只有一个被包含的 .h
文件副本。
#import == #include + guard
守卫看起来像
#ifndef <some_unique_name>
#define <some_unique_name>
<header_body>
#endif
#include guard
维基百科(宏保护、头文件保护、文件保护)——防止预处理器重复包含头文件,从而减缓构建时间。
#include
和 #import
使用类似复制/粘贴的机制——递归复制 .h
文件中的代码内容(除了 #include
和 #import
指令之外的所有内容)。这意味着结果文件不会包含 #include
和 #import
指令。
您可以通过选择 .m
文件,然后执行 "Product -> Perform Action -> Preprocess ".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
#include
替换为#import
后,编译速度明显提高,XCode智能感知响应更快。(我认为这不是我的想象)。 - bobobobo#pragma once
,那么#import
和#include
是否会完全相同? - markoj