[解決済み] define、enum、constのどれを使うべきですか?
質問
現在取り組んでいるC++のプロジェクトで フラグ という種類の値があり、これは4つの値を持つことができます。これらの4つのフラグは組み合わせることができます。フラグは、データベース内のレコードを記述し、することができます。
- 新しいレコード
- 削除されたレコード
- 変更されたレコード
- 既存のレコード
さて、各レコードについて、私はこの属性を保持したいので、私は列挙を使用することができます。
enum { xNew, xDeleted, xModified, xExisting }
しかし、コードの他の場所で、どのレコードをユーザーに見せるかを選択する必要があるので、次のように1つのパラメータとして渡せるようにしたいと思います。
showRecords(xNew | xDeleted);
というわけで、3つのアプローチが考えられるようです。
#define X_NEW 0x01
#define X_DELETED 0x02
#define X_MODIFIED 0x04
#define X_EXISTING 0x08
または
typedef enum { xNew = 1, xDeleted, xModified = 4, xExisting = 8 } RecordType;
または
namespace RecordType {
static const uint8 xNew = 1;
static const uint8 xDeleted = 2;
static const uint8 xModified = 4;
static const uint8 xExisting = 8;
}
スペース要件は重要ですが(byteとint)、重要ではありません。定義があると型安全性が失われ、また
enum
ではスペース(整数)を失い、ビット演算をしたいときにはキャストしなければならないかもしれません。しかし
const
を使うと、型安全性も失います。
uint8
が間違って入ってしまう可能性があるからです。
他にもっときれいな方法はないのでしょうか?
ない場合、何を使いますか、またその理由は?
P.S. 残りのコードは、むしろクリーンなモダンC++で
#define
のない、むしろクリーンなモダンC++です。そして、私はわずかなスペースで名前空間とテンプレートを使用しているので、それらも問題外ではありません。
どのように解決するのですか?
1つのアプローチのデメリットを減らすために戦略を組み合わせます。私は組み込みシステムで仕事をしているので、以下の解決策は、整数およびビット演算子が高速で、メモリ使用量が少なく、フラッシュ使用量も少ないという事実に基づいています。
グローバルな名前空間を定数が汚染しないように、enum を名前空間に配置します。
namespace RecordType {
enumはコンパイル時に型チェックをしたものを宣言・定義しています。引数や変数に正しい型が与えられていることを確認するために、常にコンパイル時の型チェックを行います。C++ではtypedefは必要ありません。
enum TRecordType { xNew = 1, xDeleted = 2, xModified = 4, xExisting = 8,
無効な状態に対して別のメンバーを作成する。これはエラーコードとして有用です。例えば、状態を返したいのにI/O操作に失敗した場合などです。また、デバッグの際にも便利です。初期化リストやデストラクタで使用し、変数の値が使用されるべきかどうかを知ることができます。
xInvalid = 16 };
この型には2つの目的があると考えましょう。レコードの現在の状態を追跡するためと、特定の状態のレコードを選択するためのマスクを作成するためです。インライン関数を作成し、この型の値が目的に対して有効かどうかをテストします。これによって
typedef
が単なる
int
のような値で
0xDEADBEEF
のような値が、初期化されていない変数や間違ったポイントによって、変数に含まれている可能性があります。
inline bool IsValidState( TRecordType v) {
switch(v) { case xNew: case xDeleted: case xModified: case xExisting: return true; }
return false;
}
inline bool IsValidMask( TRecordType v) {
return v >= xNew && v < xInvalid ;
}
を追加する。
using
ディレクティブを追加してください。
using RecordType ::TRecordType ;
値チェック関数は、アサートの中で、悪い値が使われたときにすぐにトラップするのに便利です。実行時にバグを素早くキャッチできれば、その分ダメージも少なくなります。
以下は、それをまとめるためのいくつかの例です。
void showRecords(TRecordType mask) {
assert(RecordType::IsValidMask(mask));
// do stuff;
}
void wombleRecord(TRecord rec, TRecordType state) {
assert(RecordType::IsValidState(state));
if (RecordType ::xNew) {
// ...
} in runtime
TRecordType updateRecord(TRecord rec, TRecordType newstate) {
assert(RecordType::IsValidState(newstate));
//...
if (! access_was_successful) return RecordType ::xInvalid;
return newstate;
}
正しい値の安全性を保証する唯一の方法は、演算子のオーバーロードを持つ専用のクラスを使用することですが、それは別の読者のための練習として残されています。
関連
-
[解決済み】テンプレートの引数1が無効です(Code::Blocks Win Vista) - テンプレートは使いません。
-
[解決済み] Java enumのメンバーを比較する:==またはequals()?
-
[解決済み] enumを列挙するには
-
[解決済み] intをenumにキャストするにはどうすればよいですか?
-
[解決済み] static_cast, dynamic_cast, const_cast, reinterpret_cast はいつ使うべきですか?
-
[解決済み] Javaで文字列値からenum値を取得する方法
-
[解決済み] C#でenumからint値を取得する
-
[解決済み] スマートポインターとは何ですか?
-
[解決済み] const int*、const int * const、int const *の違いは何ですか?
-
[解決済み] C#の[Flags]Enum属性の意味とは?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】Cygwin Make bash コマンドが見つかりません。
-
[解決済み】テンプレートの引数1が無効です(Code::Blocks Win Vista) - テンプレートは使いません。
-
[解決済み】エラー。switchステートメントでcaseラベルにジャンプする
-
[解決済み】ファイルから整数を読み込んで配列に格納する C++ 【クローズド
-
[解決済み】エラー:free(): 次のサイズが無効です(fast)。
-
[解決済み】システムが指定されたファイルを見つけられませんでした。
-
[解決済み】演算子のオーバーロード C++; <<操作のパラメータが多すぎる
-
[解決済み] スタックアロケーションにより初期化されていない値が作成された
-
[解決済み】c++で.txtファイルから2次元の配列に読み込む
-
[解決済み] C言語におけるenumのサイズは?