Objective-C の #import と #include の違いは何ですか? また、どちらか一方を使用する必要がある場合はありますか? 非推奨ですか?
私は次のチュートリアルを読んでいました: http://www.otierney.net/objective-c.html#preambleと #import と #include に関するその段落は、矛盾しているように見えるか、少なくとも不明です。
Objective-C の #import と #include の違いは何ですか? また、どちらか一方を使用する必要がある場合はありますか? 非推奨ですか?
私は次のチュートリアルを読んでいました: http://www.otierney.net/objective-c.html#preambleと #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
型が 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
最初に検出された名前のファイルの内容によってのみ置き換えられます。その後は毎回無視されます。
#import ディレクティブは、#include の改良版として Objective-C に追加されました。ただし、それが改善されるかどうかは、まだ議論の問題です。#import は、再帰的なインクルードで問題が発生しないように、ファイルが一度だけインクルードされることを保証します。ただし、ほとんどの適切なヘッダー ファイルは、いずれにせよこれに対して自身を保護するため、それほどメリットはありません。
基本的に、どちらを使用するかはあなた次第です。私は Objective-C のもの (クラス定義など) のヘッダーを #import し、必要な標準 C のものを #include する傾向があります。たとえば、ソース ファイルの 1 つは次のようになります。
#import <Foundation/Foundation.h>
#include <asl.h>
#include <mach/mach.h>
私はジェイソンに同意します。
私はこれをやっていることに気づきました:
#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 を使用します。
#include
C と同じように機能し#include
ます。
#import
どのヘッダーが既に含まれているかを追跡し、ヘッダーがコンパイル単位で複数回インポートされた場合は無視されます。これにより、ヘッダー ガードを使用する必要がなくなります。
要点は、Objective-C で使用するだけ#import
であり、ヘッダーが何かを複数回インポートすることになっても心配する必要はありません。
私はこのスレッドが古いことを知っています...しかし「現代」では..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_MODULES
in - を渡します。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 リポジトリを参照してください。
C ++とマクロに精通している場合は、
#import "Class.h"
と類似しています
{
#pragma once
#include "class.h"
}
これは、アプリの実行時にクラスが1回だけ読み込まれることを意味します。
場合によって.h
は、問題の原因となっているファイルの 1 つにグローバル変数があり、そのextern
前に追加することで解決しました。
.h ファイルにファイルを 2 回 #include すると、コンパイラはエラーを出します。ただし、ファイルを複数回 #import すると、コンパイラはそれを無視します。
#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
、これは再宣言されません。