C ++で列挙型を宣言するときにtypedefを使用するのはなぜですか?


183

私は何年もC ++を書いていないので、今はそれを取り戻そうとしています。それから私はこれに遭遇し、あきらめることを考えました:

typedef enum TokenType
{
    blah1   = 0x00000000,
    blah2   = 0X01000000,
    blah3   = 0X02000000
} TokenType;

これは何ですか?typedefここでキーワードが使用されているのはなぜですか?TokenTypeこの宣言で名前が2回表示されるのはなぜですか?これとセマンティクスはどのように違うのですか?

enum TokenType
{
    blah1 = 0x00000000,
    blah2=0x01000000,
    blah3=0x02000000
};

回答:


156

Cでは、列挙型を最初に宣言すると、次のように使用できます。

TokenType my_type;

2番目のスタイルを使用する場合は、次のように変数を宣言する必要があります。

enum TokenType my_type;

他の人が述べたように、これはC ++では違いはありません。私の推測では、これを書いた人はCプログラマーであるか、CコードをC ++としてコンパイルしているのでしょう。どちらの方法でも、コードの動作には影響しません。


12
あなたの質問はCだけに当てはまり、C ++には当てはまりません。C ++では、列挙型と構造体は、typedefがあるかのように直接使用できます。
デビッドロドリゲス-ドリベス2008

7
ええ、でも、これは本当に「これは何を意味するのか」について尋ねられた実際の質問に答えます。
BobbyShaftoe 2008

これは技術的にはtypedefまたはenumですか?
Miek

5
それは両方です。次のように言うこともできます:enum TokenType_ {...}; typedef enum TokenType_ TokenType;
ライアンフォックス

答えは完全ですが、要点はTokenTypeです。enum宣言の後は、型名を宣言するものです。したがって、答えは100%完全ではありません。「最初の方法」を宣言すると、列挙型と、その列挙型である新しい型名の両方が構文の1つのblobで指定されます。答えは役に立ちましたが、少し改善できると思います。多分私は過激すぎて反対票を投じることができませんでした。結局それを賛成した。私が本当に確信しているのであれば、私は答えを編集/改善するのにちょっとしたことをします...しかし、これはかなり良い回答です
ロスヤングブラッド

97

もしそうなら、それはCの遺産です。

enum TokenType
{
    blah1   = 0x00000000,
    blah2   = 0X01000000,
    blah3   = 0X02000000
};

あなたはそれを何かのように使う必要があります:

enum TokenType foo;

しかし、これを行うと:

typedef enum e_TokenType
{
    blah1   = 0x00000000,
    blah2   = 0X01000000,
    blah3   = 0X02000000
} TokenType;

次のように宣言できます。

TokenType foo;

ただし、C ++では、前の定義のみを使用して、Cのtypedefにあるかのように使用できます。


1
あなたの言うことはCでは真実です。C++ではそうではありません。
ジョナサンレフラー

49
私が最後の文で言ったことではありませんか?
マット

2
@mat私は最後の文についてのあなたのコメントに賛成票を投じましたが、公平を期すために、言葉遣いが不十分で混乱しています。
AR、

20

あなたはそれをする必要はありません。Cでは(C ++ではなく)、列挙型のデータ要素を参照するために列挙型Enumnameを使用する必要がありました。それを単純化するために、単一の名前データ型にtypedefすることが許可されました。

typedef enum MyEnum { 
  //...
} MyEnum;

列挙型のパラメータを取る関数を次のように定義できます

void f( MyEnum x )

長い代わりに

void f( enum MyEnum x )

typenameの名前はenumの名前と同じである必要はないことに注意してください。構造体でも同じことが起こります。

一方、C ++では、列挙型、クラス、および構造体は、名前で型として直接アクセスできるため、必要ありません。

// C++
enum MyEnum {
   // ...
};
void f( MyEnum x ); // Correct C++, Error in C

実際、私はこれが一般的に受け入れられているものよりも良い答えであると思います。なぜなら、それが「なぜ」違うのかを明確に説明しているからです。
ロスヤングブラッド

11

Cでは、型をenum以外の何かに変更できるため、スタイルとしては優れています。

typedef enum e_TokenType
{
    blah1   = 0x00000000,
    blah2   = 0X01000000,
    blah3   = 0X02000000
} TokenType;

foo(enum e_TokenType token);  /* this can only be passed as an enum */

foo(TokenType token); /* TokenType can be defined to something else later
                         without changing this declaration */

C ++では、列挙型を定義して、C ++またはCとしてコンパイルすることができます。


言うつもりはないですIn C++ you can *typedef* the enum so that it will compile as C++ or C.か?あなたは言った:In C++ you can define the enum so that it will compile as C++ or C.私はあなたの変更の通知方法defineにしますtypedef。まあ...私はtypedefING 定義していると思います。
ガブリエルステープルズ

6

Cからのホールドオーバー


Dunnoは、「初期」の修飾子が関連していると考えています。enum接頭辞なしで型名を使用したい場合は、Cで記述します。
ジョナサンレフラー

1
本当。削除します。私は長い間、C仕様に準拠していませんでした。私はc / c ++の区別をチェックするのが面倒だった...私にとっては-1。
Tim

6

Cには名前空間がないと言う人もいますが、技術的には正しくありません。3つあります。

  1. タグ(enumunion、及びstruct
  2. ラベル
  3. (ほかのすべて)

typedef enum { } XYZ;匿名の列挙を宣言し、それを名前でグローバル名前空間にインポートしますXYZ

typedef enum ABC { } XYZ;ABCタグ名前空間で名前が付けられた列挙型を宣言し、それをグローバル名前空間にとしてインポートしますXYZ

個別の名前空間に煩わされたくないので、すべてをtypedefする人もいます。名前空間が必要なため、typedefを使用しないものもあります。


これは正確ではありません。構造体、共用体、および列挙型は、タグ名で参照されます(前述のように、匿名でない限り)。タイプとタグには別々の名前空間があります。タグとまったく同じ名前のタイプを使用して、問題なくコンパイルできます。ただし、列挙型に構造体と同じタグがある場合、これは2つの構造体または同じタグを持つ2つの列挙型とまったく同じコンパイルエラーです。gotoのラベルが別の名前空間であることも忘れてください。ラベルは、タグと同じ名前、または識別子であり、タイプではない場合があります。また、識別子はタグと同じ名前で、タイプではない場合があります。
リッチヤーン2018

3

これは少し古いですが、とにかく、今年の初めに見つけたときに私がそれを感謝したとき、私が入力しようとしているリンクに感謝していただければ幸いです。

こちらです。いくつかの厄介なtypedefを把握する必要がある場合、常に私の頭にある説明を引用する必要があります。

変数宣言では、導入された名前は対応する型のインスタンスです。[...]ただし、typedefキーワードが宣言の前にある場合、導入された名前は対応するタイプのエイリアスです

以前に多くの人が言ったように、C ++では列挙型を宣言するtypedefを使用する必要はありません。しかし、それがtypedefの構文の説明です!私はそれが役に立てば幸いです(おそらく10年近く経過しているため、おそらくOPではありませんが、この種のことを理解するのに苦労している人なら誰でも)。


1

一部のCコードスタイルガイドでは、typedefバージョンが「明快さ」と「シンプルさ」のために好まれると言われています。typedefは宣言されたオブジェクトの実際の性質を難読化するため、同意しません。実際、C変数を宣言するときにオブジェクトが実際に何であるかを明確にしたいので、typedefは使用しません。この選択により、私は古いコードの一部が実際に何をしているかをより速く思い出すことができ、将来コードを保守するときに他の人を助けるでしょう。


1

「なぜ」の質問に対する実際の答え(驚くべきことに、この古い質問の上にある既存の回答では無視されます)は、このenum宣言がおそらくCとC ++の両方のコード(つまり、 CおよびC ++の実装ファイルに含まれています)。このようなヘッダーファイルを作成する技術は、両方の言語で適切な互換性のある意味を持つ言語機能を選択する作成者の能力に依存しています。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.