モーダルを閉じる工作HardwareHub ロゴ画像

工作HardwareHubは、ロボット工作や電子工作に関する情報やモノが行き交うコミュニティサイトです。さらに詳しく

利用規約プライバシーポリシー に同意したうえでログインしてください。

工作HardwareHub ロゴ画像 (Laptop端末利用時)
工作HardwareHub ロゴ画像 (Mobile端末利用時)

ダウンキャスト (C++をもう一度)

モーダルを閉じる

ステッカーを選択してください

モーダルを閉じる

お支払い内容をご確認ください

購入商品
」ステッカーの表示権
メッセージ
料金
(税込)
決済方法
GooglePayマーク
決済プラットフォーム
確認事項

利用規約をご確認のうえお支払いください

※カード情報はGoogleアカウント内に保存されます。本サイトやStripeには保存されません

※記事の執筆者は購入者のユーザー名を知ることができます

※購入後のキャンセルはできません

作成日作成日
2014/12/23
最終更新最終更新
2017/04/30
記事区分記事区分
一般公開

目次

    低レイヤーのプログラミングとOS開発が趣味。C言語を使っています。

    0
    ステッカーを贈るとは?

    実行時型情報 RTTI

    #include <iostream>
    #include <typeinfo>
    using namespace std;
    
    class MyClass {
    public:
        virtual ~MyClass() {} // typeid で正しい RTTI
        // (RunTime Type Information; 実行時型情報)
        // を得るためには少なくとも virtual 仮想関数が
        // 一つ存在することが必要です。エラーが出ずに
        // 正しい値が得られないだけなため、はまりどころです。
        // (開発環境によっては更に RTTI をオプションで有効化
        //  しなければならないこともあります)
    };
    
    class MySubClassA :
        public MyClass
    {
    };
    
    class MySubClassB :
        public MyClass
    {
    };
    
    void MyFunc(const MyClass& obj) {
        const type_info& ti = typeid(obj);
        cout << ti.name() << endl; //=> 11MySubClassA
    
        // 真偽を true/false 文字列で出力 (マニピュレータ)
        cout << boolalpha;
        cout << (ti == typeid(MyClass)) << endl; //=> false
        cout << (ti == typeid(MySubClassA)) << endl;
        //=> true (← アップキャスト前の型が判明)
        cout << (ti == typeid(MySubClassB)) << endl; //=> false
    }
    
    int main() {
        MySubClassA obj;
        MyFunc(obj);
        return 0;
    }
    

    ダウンキャスト

    実行時型情報 RTTI を頼りに、継承木の下へのキャスト (ダウンキャスト) の正しさを調査できます。dynamic_cast はアップキャストやダウンキャスト (あるいはそれらを同時に行うクロスキャスト) という、継承木におけるあるノードから別のノードへのキャストを行うために存在しています。ダウンキャスト時にはその正しさの調査を自動で行い、不正なダウンキャストに対しては例外などで知らせてくれます。アップキャスト時には正しさの調査を行う必要もないことから、わざわざ dynamic_cast を使用する利点はあまりないですが文法上は可能です。

    dynamic_cast は static_cast にダウンキャストの成功判定機能やクロスキャスト機能を付け加えたようなものであり、本質的には static_cast でも同じことが実現できます。しかしながら、ダウンキャストは危険なキャストなため、処理速度がよほど気になる場合を除き、継承木キャスト専用の dynamic_cast を使用するようにしましょう。

    #include <iostream>
    #include <typeinfo>
    using namespace std;
    
    class MyClass {
    public:
        virtual ~MyClass() {}
    };
    
    class MySubClassA :
        public MyClass
    {
    };
    
    class MySubClassB :
        public MyClass
    {
    };
    
    void MyFunc(const MyClass& obj) {
        try {
            const MySubClassA& objA = dynamic_cast<const MySubClassA&>(obj); // 成功
            const MySubClassB& objB = dynamic_cast<const MySubClassB&>(obj); // 失敗 (=> bad_cast 例外)
        }
        catch(const bad_cast& e) {
            cerr << "bad_cast" << endl; // typeinfo で定義されています
        }
    
        // ポインタの dynamic_cast では例外ではなく NULL が返ります
        const MySubClassA* ptrA = dynamic_cast<const MySubClassA*>(&obj);
        const MySubClassB* ptrB = dynamic_cast<const MySubClassB*>(&obj);
        if ( ptrA == NULL ) {
            cerr << "ptrA == NULL" << endl;
        }
        if ( ptrB == NULL ) {
            cerr << "ptrB == NULL" << endl;
        }
    }
    
    int main() {
        MySubClassA obj;
        MyFunc(obj); //=> bad_cast
                     //   ptrB == NULL
        return 0;
    }
    
    0
    詳細設定を開く/閉じる
    アカウント プロフィール画像 (本文下)

    低レイヤーのプログラミングとOS開発が趣味。C言語を使っています。

    記事の執筆者にステッカーを贈る

    有益な情報に対するお礼として、またはコメント欄における質問への返答に対するお礼として、 記事の読者は、執筆者に有料のステッカーを贈ることができます。

    さらに詳しく →
    ステッカーを贈る コンセプト画像

    Feedbacks

    Feedbacks コンセプト画像

      ログインするとコメントを投稿できます。

      関連記事

      • 競技プログラミングの基本処理チートシート (C++)
        限られた時間の中で問題を解くために必要となる、競技プログラミングにおける基本的な処理のチートシートです。競プロにおけるメジャー言語 C++ を利用します。その際 C++11 の機能は利用せず C++03 の機能の範囲内で記述します。 頻度高く定期的に開催されるコンテスト AtCoder Codeforces main.cpp #include <iostream>
      • 構造体と列挙体 (C++をもう一度)
        構造体 #include <iostream> using namespace std; struct MyStruct { char charval; int intval; }; void Show(MyStruct* obj) { cout << obj->intval << endl; } int main() { ...
      • Valgrind による C/C++ メモリリーク検出
        JVM メモリリークでは JDK の jstat や jmap で原因を調査できます。C/C++ では valgrind の Memcheck ツールが利用できます。valgrind には複数のツールが含まれており既定のツールが Memcheck です。他のツールを利用する場合は --tool オプションで指定します。 [簡単な利用例](h
        あおいねずみあおいねずみ2/27/2022に更新
        いいねアイコン画像0
      • クラスの基本/初期化 (C++をもう一度)
        構造体のように初期化する (非推奨) #include <iostream> using namespace std; const int MAX_STR = 16; class MyClass { public: int m_integer; char m_str[MAX_STR + 1]; void Show(); }; void MyClass::Show...
      • Union-Find サンプル
        『プログラミングコンテストでのデータ構造』で紹介されている Union-Find 木で集合を表現すると、以下のクエリを高速に実行できます。集合一つが一つの木となるため、複数の集合がある場合は全体として森になります。 ある要素 a_i と a_j が同じ集合に属しているかどうかの判定 二つの集合を一つの集合にまとめる サンプル [POJ 1182](https://translat