列挙型
列挙型:インデックス への移動
列挙型のデータ型は,1 組の整数値に憶えやすい識別子を与えるために使用します。たとえば次の宣言は,
enum days { sun, mon, tues, wed, thur, fri, sat } anyday;
ユニークな整数型 enum days と,この型の変数 anyday,および定数整数値を持つ 1 組の列挙子(sun,mon,...)を定義します。
-b コンパイラスイッチは,「列挙型を int で確保する」オプションを制御します。このスイッチを使用すると,コンパイラは,列挙型(enum 型の変数)にワード全体(4 バイト int)を割り当てます。値の範囲が許せばデフォルトは ON(enum が常に int であることを意味する)ですが,式中で使用される値は常に int に拡張されます。列挙子リスト中で使用される識別子は,列挙子の値によって暗黙のうちに signed char,unsigned char,あるいは int になります。すべての値が signed char か unsigned char で表せる場合は,各列挙子の型は signed char か unsigned char になります。
C では,列挙型の変数を int 型の値に代入することができます(型チェックは行われません)。C++ では,列挙型の変数に代入できるのは,その列挙子のどれかだけです。つまり次のようになります。
anyday = mon; // OK anyday = 1; // mon == 1 であっても不正
識別子 days は,以降 enum days の型の列挙型変数を宣言するときに使用できるオプションの列挙型タグです。
enum days payday, holiday; // 2 つの変数を宣言
C++ では,days が同じスコープ内のほかの名前と同じでない場合には,キーワード enum を省略することができます。
struct および union の宣言と同様に,enum 型の変数がさらに必要ではない場合には,タグを省略することができます。
enum { sun, mon, tues, wed, thur, fri, sat } anyday; /* タグなしの列挙型 */
カッコ内に一覧された列挙子は,列挙型定数とも呼ばれます。各列挙子には固定の整数値が代入されます。明示的な初期化子がない場合は,最初の列挙子(sun)はゼロにセットされ,以降の各列挙子は直前の列挙子に 1 を加えた値(mon=1,tues=2,...)がセットされます。列挙型定数の詳細については,列挙型定数を参照してください。
明示的に整数初期化子を使って,1 つ以上の列挙子に特定の値をセットすることができます。後続の初期化子がない名前は 1 ずつ増加します。たとえば以下の宣言では,
/* 初期化式にはすでに宣言されている宣言子を使ってよい */ enum coins { penny = 1, tuppence, nickel = penny + 4, dime = 10, quarter = nickel * nickel } smallchange;
tuppence の値は 2,nickel は 5,quarter は 25 になります。
初期化子には,(場合によって整数の拡張後に)正あるいは負の整数値となるどんな式でも指定できます。それらの値は通常はユニークですが,重複してもかまいません。
enum 型は int 型が使えるところであれば,どこにでも使用できます。
enum days { sun, mon, tues, wed, thur, fri, sat } anyday; enum days payday; typedef enum days DAYS; DAYS *daysptr; int i = tues; anyday = mon; // OK *daysptr = anyday; // OK mon = tues; // NG: mon は定数
列挙型タグは,構造体および共用体タグと同一の名前空間を持ちます。列挙子は,普通の変数識別子と同一の名前空間を共有します。
int mon = 11; { enum days { sun, mon, tues, wed, thur, fri, sat } anyday; /* 列挙子 mon は外側の int mon の宣言を隠す */ struct days { int i, j;}; // NG: タグ days が重複 double sat; // NG: sat の再定義 } mon = 12; // int mon のスコープに戻る
C++ では,あるクラスで宣言された列挙子は,そのクラスのスコープ内にあります。
C++ では,列挙子のほとんどの演算子をオーバーロードできます。ただし,=,[],(),および -> 演算子は,メンバー関数としてオーバーロードしなければならないので,enum にはオーバーロードできません。後置インクリメント演算子と前置インクリメント演算子のオーバーロード方法については,列挙型演算子のオーバーロード方法を参照してください。