この記事のポイント

  • Cスタイルキャストがレビューで必ず排除すべき理由を整理
  • C++キャスト種別の適用基準を解説
  • 実務コードでの改善例・レビュー観点を提示

なぜCスタイルキャストはレビュー対象なのか

Cスタイルキャスト:

(TargetType)value

この書き方は非常に危険なキャスト構文です。

問題点

問題 内容
意図不明 変換の種類がコード上から読めない
型安全性なし 無条件で変換が実行される
保守性崩壊 誰が見ても「本当に安全か?」を判断できない
誤用温床 const破壊・reinterpret誤用など

C++のレビュー原則:

Cスタイルキャストは「絶対禁止」


C++キャストの正しい適用原則

C++には用途ごとにキャスト種別が用意されています。

キャスト 用途
static_cast 明示的な通常型変換
const_cast const除去・付与
reinterpret_cast バイナリレベル型変換
dynamic_cast ポリモーフィズム安全型変換

この「明示性」こそがレビューで極めて重要です。


良い実装例

良い例:用途別C++キャスト明示
double d = 3.14;
int i = static_cast<int>(d);  // 値変換

const char* str = "abc";
char* modifiable = const_cast<char*>(str);  // const除去

uintptr_t ptrValue = reinterpret_cast<uintptr_t>(str);  // アドレス取得

良い設計理由

  • 変換理由がキャスト種別で即理解できる
  • const破壊の危険が明示されている

レビュー観点

レビューアーは以下を確認します。

  • Cスタイルキャストが残存していないか
  • キャスト理由に合ったC++キャストを使用しているか
  • static_cast濫用でなく意図があるか
  • const_castが妥当な責務範囲内でのみ使用されているか
  • reinterpret_castの使用箇所が最小限かつ説明付きか
  • dynamic_castはRTTI利用時のみ限定適用されているか

良くない実装例: ケース1

悪い例:Cスタイルキャスト残存
double d = 3.14;
int i = (int)d;
@Reviewer
Cスタイルキャストは禁止です。static_castを使用してください。

改善例

改善例:static_cast使用
int i = static_cast<int>(d);

ケース2: const破壊の危険な隠蔽

悪い例:const除去をCスタイルで
const char* str = "abc";
char* modifiable = (char*)str;
@Reviewer
const破壊が意図不明瞭です。const_cast使用で明示してください。

改善例

改善例:const_castで責任明示
char* modifiable = const_cast<char*>(str);

const_cast使用時のレビュー要注意ポイント

  • 安易なconst破壊は責務設計不備の兆候

ケース3: ポインタ型変換のバイナリ濫用

悪い例:アドレス変換をCスタイルで
void* p = getPointer();
int* intp = (int*)p;
@Reviewer
ポインタ型変換はreinterpret_castを使用してください。型安全確認ができません。

改善例

改善例:reinterpret_cast使用
int* intp = reinterpret_cast<int*>(p);

reinterpret_castは危険だが必須用途もある

  • バイナリ転送・シリアライズ・低レベルAPI
  • 必ず設計責任が明確な層のみで使用

ケース4: RTTI未使用前提のdynamic_cast濫用

悪い例:RTTI使わずdynamic_cast無効利用
Base* b = getBase();
Derived* d = (Derived*)b;
@Reviewer
ダウンキャストはdynamic_castに置き換えてください。ポインタnull確認ができます。

改善例

改善例:dynamic_cast活用
Derived* d = dynamic_cast<Derived*>(b);
if (d) {
    // 安全にDerived操作
}

dynamic_castレビューの鉄則

  • 継承階層外参照崩壊を防止可能
  • null確認必須(型不一致時)

ケース5: static_castの過剰適用誤解

悪い例:static_castに万能性を期待
void* p = getPointer();
int* intp = static_cast<int*>(p);
@Reviewer
ポインタ型変更はstatic_castでは行わずreinterpret_castを使用してください。

改善例

改善例:用途分離を厳密化
int* intp = reinterpret_cast<int*>(p);

static_castは構造的互換前提の型変換専用

  • 基本型間(int→double等)
  • 継承階層の上位・下位互換(ただし安全性保証は別)

ケース6: キャスト理由をコメントしない設計

悪い例:reinterpret_cast無説明
auto handle = reinterpret_cast<HandleType>(ptr);
@Reviewer
reinterpret_cast使用時は目的・前提条件をコメントしてください。

改善例

改善例:設計前提をコード内に残す
// 外部APIはHandleTypeにアドレスキャスト要求
auto handle = reinterpret_cast<HandleType>(ptr);

C++キャスト種別早見表

使用場面 適用キャスト コメント義務
算術型間の通常変換 static_cast 原則不要
ポインタ継承階層内変換 static_cast 継承関係意識確認
const除去 const_cast 意図説明推奨
生ポインタ変換 reinterpret_cast 必ず設計前提を記載
RTTIダウンキャスト dynamic_cast nullチェック必須

観点チェックリスト


まとめ

レビューアーは「キャスト種別が見えない=レビュー不合格」を原則に確認します。

  • C++はキャストを設計表現手段に昇格させている
  • Cスタイルキャストは安全性設計情報を破壊する

可読性・安全性・責務可視化を守るために、キャストは全て明示化する設計文化を徹底しましょう。