C++キャスト

C++のキャストについて

キャストとは

キャストとは、ある型からある型への(明示的な) 変換操作を意味します。

C言語と同様に、C++でも「(型名)変数」という指定でキャスト(型変換)することが可能です。


#include <iostream>
using namespace std;

int main()
{
    float x = 1.25;
    int   y = (int)x;
    printf("%d\n", y);
    return(0);
}

C++での拡張について

C++では、C言語のようにキャスト演算子を用いて「(データ型)式」と記述する形式に加え、「データ型(式)」という形式でも記述することができます。


int a = (double)x / y; // 従来のキャスト形式
int b = double(x) / y; // C++で追加されたキャスト形式

キャストの危険性について

C++では他のクラス型へのキャストが可能であるため、不用意にキャストを利用すると、メンバに対して不正なアクセスを行う危険性があります。

例えば、あるインスタンスへのポインタを他のインスタンス(クラス)へのポインタにキャストすると、本来指していたクラスには存在しないメンバへアクセスすることになります。

C++ではこの問題に対応するために、4つの新しいキャスト構文が追加されていますので、適切に利用する必要があります。


C++で追加されたキャスト演算子

static_cast(静的キャスト)

static_castは、コンパイル時にエラーチェックが行われ、実行時には変換後の型は決定しているキャスト方法です。

例えば、int型とlong型の変換、int型とchar型の変換などの一般的なキャストです。

なお、ポインタ型同士のキャスト(int* から char* など)は行えません。


#include <iostream>
using namespace std;

int main()
{
    float x = 3.141592;
    int   y = static_cast<int>(x);
    printf("%d\n", y);
    return(0);
}

dynamic_cast(動的キャスト)

dynamic_castは、実行時にキャスト可能かどうかを判断した上で、キャストを実行する機能です。

もし、正しくないポインタを指定してキャストした場合、キャスト結果がNULLになります。

(キャスト直後に、結果がNULLチェックすることでキャストの失敗を検出できます。)


下記例では、サブクラスCSubのスーパークラスCBaseが明示的である(保証されている)場合のキャストは成功し、明示されていない状態では失敗する例です。

(コンパイラによっては、コンパイル時にワーニングが表示されるかもしれません。)


#include <iostream>

class CBase{
public:
    virtual ~CBase(void){}
    void func(void){}
};
class CSub : public CBase{};

int main()
{
    CSub  sub_obj;
    CBase *base_obj1 = &sub_obj;
    CBase base_obj2;

    // サブクラスのスーパークラスが保証されているキャストは成功する
    CSub *p1 = dynamic_cast<CSub *>(base_obj1);
    if(p1 == NULL){
        printf("ERROR: failed to dynamic cast: p1\n");
        return(1);
    }

    // サブクラスのスーパークラスが保証されていないキャストは失敗する
    CSub *p2 = dynamic_cast<CSub *>(&base_obj2);
    if(p2 == NULL){
        printf("ERROR: failed to dynamic cast: p2\n");
        return(1);
    }

    return(0);
}

const_cast

const_castは、「const」や「volatile」を無効化するキャストです。

不正なキャストである場合、コンパイルエラーになります。

const属性は、そもそも書き換えを禁止するために付けますので、外すことが危険な動作であることを注意する必要があります。


#include <iostream>

int main()
{
    const char *str = "Hello World!";
    char *cp = const_cast<char *>(str);
    printf("%s\n", cp);
    return(0);
}

reinterpret_cast(再解釈キャスト)

reinterpret_castは強制的にビット構成を変更(再解釈)するキャストであり、根本的に異なる型同士のキャストに使います。

例えば、ポインタ型同士の変換や、int型の変数をポインタ型に変換する場合などに使います。

constやvolatileの除去は出来ませんし、継承関係にあってもポインタは再計算されません。

あまり使う機会はありませんが、Win32APIではわずかに利用する場面があります。


#include <iostream>

int main()
{
    long num = 1111;
    int *np = reinterpret_cast<int *>(num);

    printf("%d\n", np);
    return(0);
}

関連ページ