399

Objective-C の #import と #include の違いは何ですか? また、どちらか一方を使用する必要がある場合はありますか? 非推奨ですか?

私は次のチュートリアルを読んでいました: http://www.otierney.net/objective-c.html#preambleと #import と #include に関するその段落は、矛盾しているように見えるか、少なくとも不明です。

4

10 に答える 10

374

プリプロセッサに関しては多くの混乱があるようです。

その行をインクルードされたファイルの内容に置き換えることを確認したときにコンパイラが何をするか、#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型が 2 回定義されているため、コンパイラ エラーが発生します。定義は同じですが、これは C 言語では許可されていません。

ヘッダーは複数の場所で使用されることが多いため、C では通常インクルード ガードが使用されます。これは次のようになります。

 #ifndef _a_h_included_
 #define _a_h_included_

 typedef int my_number;

 #endif

ファイルb.cには、前処理された後でも、ヘッダーの内容全体が 2 回含まれています。ただし、マクロ_a_h_included_は既に定義されているため、2 番目のインスタンスは無視されます。

これは非常にうまく機能しますが、2 つの欠点があります。まず、インクルード ガードを記述する必要があり、マクロ名はすべてのヘッダーで異なる必要があります。次に、コンパイラはヘッダー ファイルを探して、インクルードされるたびに読み取る必要があります。

Objective-C には#importプリプロセッサ命令があります (一部のコンパイラとオプションを使用して、C および C++ コードにも使用できます)。これは とほぼ同じ#includeですが、どのファイルが既に含まれているかを内部的に記録します。行は、#import最初に検出された名前のファイルの内容によってのみ置き換えられます。その後は毎回無視されます。

于 2010-09-17T22:38:15.120 に答える
356

#import ディレクティブは、#include の改良版として Objective-C に追加されました。ただし、それが改善されるかどうかは、まだ議論の問題です。#import は、再帰的なインクルードで問題が発生しないように、ファイルが一度だけインクルードされることを保証します。ただし、ほとんどの適切なヘッダー ファイルは、いずれにせよこれに対して自身を保護するため、それほどメリットはありません。

基本的に、どちらを使用するかはあなた次第です。私は Objective-C のもの (クラス定義など) のヘッダーを #import し、必要な標準 C のものを #include する傾向があります。たとえば、ソース ファイルの 1 つは次のようになります。

#import <Foundation/Foundation.h>

#include <asl.h>
#include <mach/mach.h>
于 2009-01-13T16:29:54.953 に答える
65

私はジェイソンに同意します。

私はこれをやっていることに気づきました:

#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> は#defines を使用して <time.h>の一部のみを含めます

あなたは #import <time.h>: いけ
    ません。<time.h> の一部しか既にインクルードされていませんでしたが、
    #import に関する限り、そのファイルは既に完全にインクルードされています。

結論:

C/C++ ヘッダーには、従来、他のインクルード ファイルの一部が含まれていました。
したがって、C/C++ ヘッダーには #include を使用します。
objc/objc++ ヘッダーの場合は、#import を使用します。

于 2010-11-18T20:51:47.693 に答える
26

#includeC と同じように機能し#includeます。

#importどのヘッダーが既に含まれているかを追跡し、ヘッダーがコンパイル単位で複数回インポートされた場合は無視されます。これにより、ヘッダー ガードを使用する必要がなくなります。

要点は、Objective-C で使用するだけ#importであり、ヘッダーが何かを複数回インポートすることになっても心配する必要はありません。

于 2009-01-13T16:28:39.263 に答える
14

私はこのスレッドが古いことを知っています...しかし「現代」では..clangの@importモジュールを介したはるかに優れた「インクルード戦略」があります-それは見過ごされがちです..

モジュールは、テキスト プリプロセッサ インクルージョン モデルをより堅牢で効率的なセマンティック モデルに置き換えることで、ソフトウェア ライブラリの API へのアクセスを改善します。ユーザーの観点からは、#include プリプロセッサ ディレクティブではなく import 宣言を使用するため、コードはわずかに異なるように見えます。

@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 をアプリケーションで直接使用できるようにします。import 宣言の前にあるプリプロセッサ定義は、提供される API に影響を与えません... モジュール自体が別のスタンドアロン モジュールとしてコンパイルされているためです。さらに、モジュールを使用するために必要なリンカー フラグは、モジュールのインポート時に自動的に提供されます。このセマンティック インポート モデルは、プリプロセッサの包含モデルの問題の多くに対処します。

モジュールを有効にするには、コンパイル時にコマンドライン フラグ-fmodules別名CLANG_ENABLE_MODULESin - を渡します。Xcode上記のように..この戦略は ANY と ALL を取り除きLDFLAGSます。同様に、「OTHER_LDFLAGS」設定と「リンク」フェーズを削除できます。

ここに画像の説明を入力

コンパイル/起動時間がより速く「感じる」ことがわかりました(または、「リンク」中のラグが少ないだけですか?)..また、不要になった Project-Prefix.pch ファイルをパージする絶好の機会を提供します。対応するビルド設定GCC_INCREASE_PRECOMPILED_HEADER_SHARING、、、、GCC_PRECOMPILE_PREFIX_HEADERなどGCC_PREFIX_HEADER

また、十分に文書化されていませんが…module.map独自のフレームワーク用に を作成し、同じ便利な方法でそれらを含めることができます。 このような奇跡を実装する方法の例については、私の ObjC-Clang-Modules github リポジトリを参照してください。

于 2014-04-18T01:37:44.343 に答える
4

C ++とマクロに精通している場合は、

#import "Class.h" 

と類似しています

{
#pragma once

#include "class.h"
}

これは、アプリの実行時にクラスが1回だけ読み込まれることを意味します。

于 2012-10-18T12:56:27.683 に答える
1

場合によって.hは、問題の原因となっているファイルの 1 つにグローバル変数があり、そのextern前に追加することで解決しました。

于 2015-08-10T15:47:32.430 に答える
0

.h ファイルにファイルを 2 回 #include すると、コンパイラはエラーを出します。ただし、ファイルを複数回 #import すると、コンパイラはそれを無視します。

于 2010-07-16T09:43:02.917 に答える
0

#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

コードに「otherfile.h」をn回入れても#include、これは再宣言されません。

于 2009-12-01T22:39:38.813 に答える