ダウンキャスト

http://www.geocities.jp/ky_webid/cpp/language/024.html

ダウンキャストの話です。

ダウンキャストは、継承関係の上から下へ向かうキャストです。

基底クラスから派生クラスへのキャストになります。

とにかく実際の処理を見てみましょう。

#include <iostream>
using namespace std;

class CBase {
};

class CSub : public CBase {
};

int main () {
    CSub* pSub = new CSub;
    CBase* pBase = pSub;
    
    pSub = dynamic_cast<CSub*>( pBase );
    if ( pSub == NULL ) {
        cout << "ダウンキャストに失敗しました" << endl;
    }
    
    return 0;
}

と、これでコンパイルしたらエラーがでました。

$ cl /W4 /EHs main.cpp
Microsoft(R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.01 for 80x86
Copyright (C) Microsoft Corporation.  All rights reserved.

main.cpp
main.cpp(14) : error C2683: 'dynamic_cast' : 'CBase' はポリモーフィックな型では
ありません。
        main.cpp(4) : 'CBase' の宣言を確認してください。

要するにダウンキャストをする場合は、対象のクラスが多態性、つまり動的結合なクラスでないと駄目なようです。

なのでとりあえず仮想デストラクタを用意しましょう。

#include <iostream>
using namespace std;

class CBase {
public:
    virtual ~CBase () {}
};

class CSub : public CBase {
};

int main () {
    CSub* pSub = new CSub;
    CBase* pBase = pSub;
    
    pSub = dynamic_cast<CSub*>( pBase );
    if ( pSub == NULL ) {
        cout << "ダウンキャストに失敗しました" << endl;
    }
    
    return 0;
}

これでばっちり処理が通りました。

ダウンキャストの場合、失敗時にNULLが返るのでチェックしましょう。

さてじゃあどういった場合にNULLが返る可能性があるのか?

それはダウンキャストしたいクラスのポインタを持っていない場合になります。

例を見たほうが早いですね。

#include <iostream>
using namespace std;

class CBase {
public:
    virtual ~CBase () {}
};

class CSub : public CBase {
};

int main () {
    CBase* pBase = new CBase;
    
    CSub* pSub = dynamic_cast<CSub*>( pBase );
    if ( pSub == NULL ) {
        cout << "ダウンキャストに失敗しました" << endl;
    }
    
    return 0;
}
$ main
ダウンキャストに失敗しました

つまりpBaseにはCBaseクラスのポインタが格納されているだけなのでそれをCSubにダウンキャストしようとしてもできないわけなんですね。