TechCraft – エンジニアのためのスキルアップメモ

エンジニアのスキルアップを少しでも加速する技術ブログ

キャストの挙動を解説するC++中級者向けガイド

C++におけるキャストの種類と挙動の違い【中級者向け】

C++では、型変換(キャスト)を使うことで異なる型同士の値を操作することが可能です。しかし、キャストの使い方を誤ると、未定義動作やセキュリティリスクにつながることもあります。

本記事では、C++におけるキャストの種類とその特徴・挙動の違いについて詳しく解説します。static_castdynamic_castconst_castreinterpret_cast のそれぞれの使い方と注意点を具体例とともに整理します。


1. C言語スタイルのキャスト(旧来のキャスト)

int i = 42;
double d = (double)i;  // C言語スタイルのキャスト

特徴

  • 書き方が簡単
  • static_cast, const_cast, reinterpret_cast などを包括しており、危険
  • どのような変換が行われているか分かりにくく、可読性が低い

推奨度

  • 非推奨(特にC++では避けるべき)

2. static_cast

double d = 3.14;
int i = static_cast<int>(d); // 明示的な数値変換

特徴

  • 基本型同士(int → double など)の変換に使える
  • クラスのポインタ/参照のアップキャストに使える(安全)
  • 暗黙的に許される変換を明示的に書ける

使用例(クラス継承)

class Base {};
class Derived : public Base {};

Derived d;
Base* b = static_cast<Base*>(&d);  // OK: 安全なアップキャスト

注意点

  • ダウンキャストに使うと未定義動作を引き起こす可能性あり

3. dynamic_cast

class Base {
public:
    virtual void func() {}
};
class Derived : public Base {};

Base* b = new Derived();
Derived* d = dynamic_cast<Derived*>(b);

特徴

  • 安全なダウンキャストに使用
  • 基底クラスに仮想関数(vtable)が必要
  • 失敗するとポインタ版は nullptr を返す、参照版は bad_cast 例外

使用例(成功と失敗)

Base* b = new Base();
Derived* d = dynamic_cast<Derived*>(b);  // 失敗 -> nullptr

注意点

  • ランタイムコストがある(RTTIが有効である必要がある)

4. const_cast

void func(const int* p) {
    int* q = const_cast<int*>(p);
    *q = 100;  // 未定義動作の可能性あり
}

特徴

  • constvolatile修飾子を取り除く
  • 定数オブジェクトへの書き込みは未定義動作

安全な使用例(読み取り専用APIに渡すため)

void legacyAPI(char* buffer);
const char* msg = "Hello";
legacyAPI(const_cast<char*>(msg));  // 書き換えない保証がある場合はOK

5. reinterpret_cast

int i = 1234;
char* p = reinterpret_cast<char*>(&i);

特徴

  • 型の再解釈(ポインタ・整数間の変換など)
  • 非常に危険で、使用には十分注意が必要
  • 型システムを無視するので、可搬性が損なわれる

使用例

uintptr_t addr = reinterpret_cast<uintptr_t>(p);  // ポインタ → 整数
MyStruct* s = reinterpret_cast<MyStruct*>(addr);  // 整数 → ポインタ

注意点


6. まとめ:キャストの使い分け

キャスト 主な用途 安全性 備考
static_cast 基本型の変換、アップキャスト 暗黙の変換を明示的に
dynamic_cast ダウンキャスト 中〜高 RTTI必須。失敗時にnullになる
const_cast const除去 書き換えない用途限定
reinterpret_cast 型再解釈(ポインタ・整数変換など) 可搬性と安全性に注意
Cスタイル 上記全てを包含(曖昧で危険) 最低 C++では非推奨

7. 補足:RTTIを無効化している場合

プロジェクトで-fno-rttiなどを指定している場合、dynamic_castは使えません。その際は型安全を保つ仕組みを自作するか、設計の見直しが必要です。


8. 参考文献・外部リンク


C++ではキャストは非常に強力なツールですが、誤用すると深刻なバグにつながります。それぞれのキャストの意図と挙動を正しく理解し、安全に使い分けることが重要です。

参考書籍