В чем разница между #import и #include в Objective-C?
каковы различия между #import и #include в Objective-C и есть ли времена, когда вы должны использовать один над другим? Один из них устарел?
Я читал следующий учебник:http://www.otierney.net/objective-c.html#preamble и его абзац о #import и #include, похоже, противоречит самому себе или, по крайней мере, неясен.
9 ответов:
директива #import была добавлена в Objective-C как улучшенная версия #include. Однако улучшилось ли оно или нет, все еще остается предметом дебатов. #import гарантирует, что файл будет включен только один раз, чтобы у вас никогда не возникало проблем с рекурсивными включениями. Тем не менее, большинство приличных заголовочных файлов защищают себя от этого в любом случае, так что это не так уж много пользы.
в принципе, это до вас, чтобы решить, какие вы хотите использовать. Я склонен #импортировать заголовки для Objective-C вещи (например, определения классов и т. д.) и #включают стандартные вещи C, которые мне нужны. Например, один из моих исходных файлов может выглядеть так:
#import <Foundation/Foundation.h> #include <asl.h> #include <mach/mach.h>
там, кажется, много путаницы в отношении препроцессора.
что делает компилятор, когда он видит
#includeчто он заменяет эту строку содержимым включенных файлов, никаких вопросов не задавалось.так что если у вас есть файл
a.hС таким содержанием:typedef int my_number;и С таким содержанием:
#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_уже определены.это работает очень хорошо, но имеет два недостатка. Прежде всего, должны быть написаны включенные охранники, и имя макроса должно быть разным в каждом заголовке. А во-вторых компилятор должен еще искать файл заголовка и читать его так часто, как он включен.
цель-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
:
включает только a часть в с помощью #defines вы #import
:
Бесполезный. Даже если только часть уже был включен, как
что касается #import, то этот файл теперь уже полностью включено.итог:
заголовки C/C++ традиционно включают частей другие включаемые файлы.
Поэтому для заголовков C/C++ используйте #include.
Для заголовков objc / objc++ используйте #import.
#includeработает так же, как C#include.
#importотслеживает, какие заголовки уже были включены и игнорируется, если заголовок импортируется более одного раза в единице компиляции. Это делает ненужным использование защитников заголовков.в нижней строке просто использовать
#importв Objective-C и не волнуйтесь, если ваши заголовки будут импортировать что-то более одного раза.
Я знаю, что этот поток старая... но в "Новое время".. существует намного превосходящая стратегия "включить" через из Clang
@importмодули - это часто упускается из виду..модули улучшают доступ к API программных библиотек, заменяя текстовую модель включения препроцессора более надежной и эффективной семантической моделью. С точки зрения пользователя, код выглядит только немного иначе, потому что он использует объявление импорта, а не # включить директиву препроцессора:
@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... потому что сам модуль был скомпилирован как отдельный автономный модуль. Кроме того, любые флаги компоновщика, необходимые для использования модуля, будут автоматически при условии, когда модуль импортируется. Эта семантическая модель импорта решает многие проблемы модели включения препроцессора.
чтобы включить модули, передайте флаг командной строки
-fmodulesакаCLANG_ENABLE_MODULESнаXcode- во время компиляции. Как уже упоминалось выше.. эта стратегия устраняет все и всяLDFLAGS. Как и в, ВЫ можете удалить любые " OTHER_LDFLAGS" настройки, а также любые "связывающие" фазы..
Я нахожу время компиляции / запуска, чтобы "чувствовать" намного быстрее (или, возможно, просто меньше задержки при "связывании"?).. а также, предоставляет отличную возможность очистить теперь уже посторонний проект-приставку.PCH-файл и соответствующие настройки сборки,
GCC_INCREASE_PRECOMPILED_HEADER_SHARING,GCC_PRECOMPILE_PREFIX_HEADERиGCC_PREFIX_HEADERи т. д.кроме того, в то время как не хорошо документированы... вы можете создать
module.maps для ваших собственных рамок и включают их в такая же удобная мода. вы можете взглянуть на мои ObjC-Clang-модули GitHub repo для некоторых примеров того, как реализовать такие чудеса.
Если вы знакомы с C++ и макросы, то
#import "Class.h"похож на
{ #pragma once #include "class.h" }это означает, что ваш класс будет загружен только один раз при запуске приложения.
Если вы #включите файл два раза.h файлов, чем компилятор даст ошибку. Но если вы # импортируете файл более одного раза, компилятор проигнорирует его.
в мае случае у меня была глобальная переменная в одном из моих
.hфайлы, которые вызывали проблему, и я решил ее, добавивexternперед ним.
#includeэто используется, чтобы получить "вещи" из другого файла в один#includeиспользуется в. Например:in file: main.cpp
#include "otherfile.h" // some stuff here using otherfile.h objects, // functions or classes declared insideзащита заголовка используется в верхней части каждого файла заголовка (*.h) чтобы предотвратить включение одного и того же файла более одного раза (если это произойдет, вы получите ошибки компиляции).
in file: otherfile.h
#ifndef OTHERFILE #define OTHERFILE // declare functions, classes or objects here #endifдаже если вы положите
#include"otherfile.h " N раз в вашем коде, это внутри него не будет будьте переоформлены.

Comments