C++レビューで必ず排除すべきCスタイルキャスト|キャスト明示で意図を伝える設計原則
この記事のポイント
- 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;
@ReviewerCスタイルキャストは禁止です。static_castを使用してください。
改善例
改善例:static_cast使用
int i = static_cast<int>(d);
ケース2: const破壊の危険な隠蔽
悪い例:const除去をCスタイルで
const char* str = "abc";
char* modifiable = (char*)str;
@Reviewerconst破壊が意図不明瞭です。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);
@Reviewerreinterpret_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スタイルキャストは安全性設計情報を破壊する
可読性・安全性・責務可視化を守るために、キャストは全て明示化する設計文化を徹底しましょう。