2009-06-03 56 views
47

Objective-Cプログラムで列挙型の可視性に問題があります。私は2つのヘッダーファイルを持っていて、1つはtypedef enumを定義しています。別のファイルではtypedef 'タイプを使用する必要があります。Objective-Cの前方宣言enum

他のヘッダーファイルは#includeですが、Objective-Cでは、代わりに@class宣言を必要に応じて使用して、ヘッダーファイル間に#importを使用しないことをお勧めします。しかし、列挙型を前方宣言する方法を理解することはできません。

対応する.m実装ファイル(実際には#import離れている)を除いて、実際の列挙値は必要ありません。では、どうすればtypedef enumをヘッダーで認識させることができますか?

+0

(スウィフト3、2017)に見えます私の答えで。 http://stackoverflow.com/a/42009056/342794 – lal

答えて

18

#importを使用してください。可能であれば人々が@classを使用することを推奨する唯一の理由は、コードを少し速くコンパイルするためです。ただし、1つの.hファイルを別の.hファイルから作成する場合は問題はありません。実際には、別のクラスを拡張するときにこれを行う必要があります。

+1

#importを使用せずに上記のことが可能ですか?単に 'typedef int EnumName'を実行するのはどうでしょうか? –

+1

私はそうは思わない。 gsの答えのリンクを参照してください:http://stackoverflow.com/questions/71416/forward-declaring-an-enum-in-c –

+0

#importコンパイルには分が必要ですが、とにかく有線のものがあります。 –

0

いずれにしても#importか、typedefのみを含む別のヘッダーファイルを作成する必要があります。ヘッダーファイルをヘッダーにインポートしないと、コンパイルは高速になりますが、他のものは変更されません。

Why doesn't C++ support forward declaration of enums?

16

あなたの質問への答えは先に行くとtypedefのヘッダファイルをインポートしたり、NSIntegerなどの一般的なタイプの代わりに、列挙型を使用するようにするかです。

しかし、ヘッダーファイルをインポートしない理由は、コンパイル速度だけではありません。

ヘッダーファイルをインポートしないと、無関係な外部クラスへのアクセスも減少します。

たとえば、特定のファイルへの変更をファイルシステムで追跡するTrackFileChangesクラスがあり、ファイルからキャッシュされたデータを格納するCachedFileクラスがあるとします。後者はTrackFileChanges *タイプのプライベートivarを使用するかもしれませんが、CachedFileを使用する場合、実装の詳細です(理想的には、新しいランタイムを使用するプライベートプロパティを持つivarが自動的に生成されますが、古いランタイムを使用して)。

#import "CachedFile.h"のクライアントは、おそらくTrackFileChanges.hを必要としないか、アクセスしたくないクライアントです。彼らがそうするならば、彼らは自分自身を#インポートすることでそれを明らかにするべきです。 @class TrackFileChanges insteaの#import "TrackFileChanges.h"をCachedFile.hで使用すると、カプセル化が改善されます。

しかし、2番目のヘッダーが最初のすべてのクライアントに公開されたい場合、2番目のヘッダーファイルからヘッダーファイルをインポートすることには何の意味もありません。たとえば、クラスを宣言するヘッダーファイルは、サブクラス化ヘッダーファイルに直接インポートする必要があり、プロトコルを宣言するヘッダーファイルを直接インポートすることもできます(ただし、これを避けるため、@protocol ABCを使用できます)。

4

あなたはコンパイラ拡張を使用して[OK]をしている場合は、クランで、この順番を使用することができます。

enum Enum; 
typedef enum Enum Enum2; 

void f(Enum2); // ok. it sees this type's true name. 

enum Enum { 
    E_1 
}; 

// ok. now its declaration is visible and we can use it. 

void f(Enum2 e) { 

} 

注:それは-Wpedantic警告がトリガされます。


C++ 11を使用している場合は、宣言を転送するのに安全なenumを使用する必要があります。 enum class Enum:uint8_t;(コンパイラ拡張ではありません)。 ;

+1

この答えを簡単にすることができます: 'typedef enum Enum Enum;'次に、メソッド定義と宣言にEnumを使用します。 –

15

最新の方法(スウィフト3 2017月)Objective-Cで列挙型(NS_ENUM/NS_OPTION)を宣言転送するには、以下を使用することです:最近の答えを

// Forward declaration for XYZCharacterType in other header say XYZCharacter.h 
typedef NS_ENUM(NSUInteger, XYZCharacterType); 


// Enum declaration header: "XYZEnumType.h" 
#ifndef XYZCharacterType_h 
#define XYZCharacterType_h 

typedef NS_ENUM(NSUInteger, XYZEnumType) { 
    XYZCharacterTypeNotSet, 
    XYZCharacterTypeAgent, 
    XYZCharacterTypeKiller, 
}; 

#endif /* XYZCharacterType_h */` 
+1

すぐに私のために働いた3 – stringRay2014

+3

今日受け入れられるはずの答え – citxx

+1

私は古いObjective Cコードを整理する方法として、昨日typedef NS_ENUMを見て始めました。 – Greg

関連する問題