C++
 Computer >> コンピューター >  >> プログラミング >> C++

C++のstatic_castとdynamic_castの違いと使い分けを徹底解説


static_castとは

static_castは、通常の型変換に使用されるキャストです。コンパイラが行う暗黙の型変換(implicit type coercion)も担当しており、明示的に記述することも可能です。floatからintcharからintへの変換のように、基本的な数値型同士の変換に適しています。また、継承関係にあるクラス間のポインタ変換にも利用できます。ただし、互換性のない型同士の変換を試みると、コンパイル時にエラーが発生します。

コード例

#include<iostream>
using namespace std;
class Base {};
class Derived : public Base {};
class MyClass {};
main(){
    Derived* d = new Derived;
    Base* b = static_cast<Base*>(d); // この行は正常に動作する
    MyClass* x = static_cast<MyClass*>(d); // コンパイル時にERRORが生成される
}

出力結果

[Error] invalid static_cast from type 'Derived*' to type 'MyClass*'

上記の例では、Derived*からBase*への変換は継承関係があるため問題なく成功します。一方、継承関係にないMyClass*への変換は無効な操作とみなされ、コンパイルエラーとなります。

dynamic_castとは

dynamic_castは、ポリモーフィズム(多態性)を扱うために使用されるキャストです。このキャストを使用するのは、派生クラスへキャストする場合のみです。つまり、継承関係において基底クラスから派生クラスへキャストする(ダウンキャストする)際に専用で使われます。実行時に実際のオブジェクトの型がチェックされ、キャストが失敗した場合はヌルポインタが返されるため、安全な型変換を実現できます。

コード例

#include<iostream>
using namespace std;
class MyClass1 {
    public:
        virtual void print()const {
            cout << "This is from MyClass1\n";
        }
};
class MyClass2 {
    public:
        virtual void print()const {
            cout << "This is from MyClass2\n";
        }
};
class MyClass3: public MyClass1, public MyClass2 {
    public:
        void print()const {
            cout << "This is from MyClass3\n";
        }
};
int main(){
    MyClass1* a = new MyClass1;
    MyClass2* b = new MyClass2;
    MyClass3* c = new MyClass3;
    a -> print();
    b -> print();
    c -> print();
    b = dynamic_cast< MyClass2*>(a); // このキャストは失敗する
    if (b)
        b->print();
    else
        cout << "no MyClass2\n";
    a = c;
    a -> print(); // MyClass3から出力される
    b = dynamic_cast< MyClass2*>(a); // キャストに成功
    if (b)
        b -> print();
    else
        cout << "no MyClass2\n";
}

出力結果

This is from MyClass1
This is from MyClass2
This is from MyClass3
no MyClass2
This is from MyClass3
This is from MyClass3

この例では、最初にMyClass1型のポインタaMyClass2型へキャストしようとした処理は失敗し、「no MyClass2」が出力されます。これはaが実際にはMyClass2と無関係なオブジェクトを指しているためです。その後、aMyClass3のインスタンスを代入してから再度キャストすると、MyClass3MyClass2を継承しているため今度は成功し、正しくMyClass3のメソッドが呼び出されます。


  1. C++のキャスト演算子を使い分けよう!static_cast・dynamic_cast・const_cast・reinterpret_castの違いと使いどころ

    C++には、C言語形式のキャストとは異なる4種類のキャスト演算子が用意されています。それぞれ目的と安全性が異なるため、状況に応じて適切に使い分けることが重要です。本記事では、const_cast、static_cast、dynamic_cast、reinterpret_castのそれぞれの役割と使用場面を詳しく解説します。 const_cast:const性(定数性)の追加・除去 const_castは、変数に対してconstを取り除いたり、逆に追加したりするための専用キャストです。const指定された変数から定数性を外す必要がある場合や、定数性を付与したい場合に使用します。 ただし、本来書

  2. C++のフレンド関数とフレンドクラスの基本を解説

    C++におけるフレンド関数(friend function)とは、クラスのスコープ外で定義される関数でありながら、そのクラスのすべてのprivateメンバーおよびprotectedメンバーにアクセスする権限を持つ特別な関数です。フレンド関数のプロトタイプ(宣言)はクラス定義の中に記述しますが、あくまで「友達」として扱われるだけであり、クラスのメンバー関数にはなりません。この点は重要なポイントです。フレンドとして指定できるものフレンドとして宣言できるのは、以下のようなものです。通常の関数関数テンプレート他のクラスのメンバー関数クラス全体(この場合、そのクラスのすべてのメンバーがフレンドになります