В чем разница между #import и #include в Objective-C?



каковы различия между #import и #include в Objective-C и есть ли времена, когда вы должны использовать один над другим? Один из них устарел?



Я читал следующий учебник:http://www.otierney.net/objective-c.html#preamble и его абзац о #import и #include, похоже, противоречит самому себе или, по крайней мере, неясен.

949   9  

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" настройки, а также любые "связывающие" фазы..

enter image description here

Я нахожу время компиляции / запуска, чтобы "чувствовать" намного быстрее (или, возможно, просто меньше задержки при "связывании"?).. а также, предоставляет отличную возможность очистить теперь уже посторонний проект-приставку.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

    Ничего не найдено.