[解決済み] C++のdynamic_castとstatic_cast
質問
について、かなり混乱しています。
dynamic_cast
というキーワードを C++ で使用することができます。
struct A {
virtual void f() { }
};
struct B : public A { };
struct C { };
void f () {
A a;
B b;
A* ap = &b;
B* b1 = dynamic_cast<B*> (&a); // NULL, because 'a' is not a 'B'
B* b2 = dynamic_cast<B*> (ap); // 'b'
C* c = dynamic_cast<C*> (ap); // NULL.
A& ar = dynamic_cast<A&> (*ap); // Ok.
B& br = dynamic_cast<B&> (*ap); // Ok.
C& cr = dynamic_cast<C&> (*ap); // std::bad_cast
}
と定義されています。
は、その
dynamic_cast
キーワードは、あるポインタまたは参照からデータをキャストします。 型から別の型へのキャストの妥当性を実行時にチェックします。
に相当するものを書けるか?
dynamic_cast
C++をCで書くと、もっとよく理解できるようになりますか?
どのように解決するのですか?
以下は、その概要です。
static_cast<>
と
dynamic_cast<>
特にポインターに関連するものです。 これは101レベルの概要であり、すべての複雑な部分をカバーしているわけではありません。
static_cast< Type* >(ptr)
のポインタを取得します。
ptr
という型のポインタに安全にキャストしようとします。
Type*
. このキャストはコンパイル時に行われます。 このキャストは
型が関連している
. 型が関連していない場合、コンパイラーエラーが発生します。 例えば
class B {};
class D : public B {};
class X {};
int main()
{
D* d = new D;
B* b = static_cast<B*>(d); // this works
X* x = static_cast<X*>(d); // ERROR - Won't compile
return 0;
}
dynamic_cast< Type* >(ptr)
これはまた、ポインタを
ptr
型のポインタに安全にキャストします。
Type*
. しかし、このキャストは、コンパイル時ではなく、実行時に実行されます。 これは実行時のキャストなので,特にポリモーフィックなクラスと組み合わせたときに便利です. 実際,ある種のケースでは
が必要です。
を使用すると、キャストが有効になります。
キャストには、ベースから派生へ(B2D)と派生からベースへ(D2B)の2つの方向があります。 D2Bのキャストが実行時にどのように機能するかは簡単だ。 どちらかというと
ptr
から派生したもので
Type
か、そうでなかったのか。 D2Bのdynamic_cast<>の場合、ルールは単純です。 何かを他の何かにキャストしようとし、もし
ptr
から派生したもので、実際には
Type
を取得します。
Type*
からポインタを返します。
dynamic_cast
. そうでない場合は、NULLポインタを取得することになります。
しかし、B2Dのキャストはもう少し複雑です。 次のようなコードを考えてみましょう。
#include <iostream>
using namespace std;
class Base
{
public:
virtual void DoIt() = 0; // pure virtual
virtual ~Base() {};
};
class Foo : public Base
{
public:
virtual void DoIt() { cout << "Foo"; };
void FooIt() { cout << "Fooing It..."; }
};
class Bar : public Base
{
public :
virtual void DoIt() { cout << "Bar"; }
void BarIt() { cout << "baring It..."; }
};
Base* CreateRandom()
{
if( (rand()%2) == 0 )
return new Foo;
else
return new Bar;
}
int main()
{
for( int n = 0; n < 10; ++n )
{
Base* base = CreateRandom();
base->DoIt();
Bar* bar = (Bar*)base;
bar->BarIt();
}
return 0;
}
main()
どのようなオブジェクトかわからない
CreateRandom()
が返されるので、C言語スタイルのキャスト
Bar* bar = (Bar*)base;
は明らかに型安全ではありません。 どうしたらこれを解決できるでしょうか。 一つの方法は、boolのような関数を追加することだ。
AreYouABar() const = 0;
をベースクラスに追加し
true
から
Bar
と
false
から
Foo
. しかし、もう1つの方法があります。
dynamic_cast<>
:
int main()
{
for( int n = 0; n < 10; ++n )
{
Base* base = CreateRandom();
base->DoIt();
Bar* bar = dynamic_cast<Bar*>(base);
Foo* foo = dynamic_cast<Foo*>(base);
if( bar )
bar->BarIt();
if( foo )
foo->FooIt();
}
return 0;
}
キャストは実行時に実行され、オブジェクトに問い合わせ(今のところ方法は気にする必要はありません)、それが探している型かどうかを尋ねることで動作します。 もしそうなら
dynamic_cast<Type*>
はポインタを返し、それ以外の場合はNULLを返します。
このベースから派生へのキャスティングを行うために
dynamic_cast<>
ベース、Foo、Barは、標準では
ポリモーフィック型
. 多相型であるためには,クラスは少なくとも1つの
virtual
関数を使用します。 クラスが多相型でない場合、ベースから派生への使用は
dynamic_cast
はコンパイルされません。 例
class Base {};
class Der : public Base {};
int main()
{
Base* base = new Der;
Der* der = dynamic_cast<Der*>(base); // ERROR - Won't compile
return 0;
}
baseに仮想dtorのような仮想関数を追加すると、BaseとDerの両方が多相型になります。
class Base
{
public:
virtual ~Base(){};
};
class Der : public Base {};
int main()
{
Base* base = new Der;
Der* der = dynamic_cast<Der*>(base); // OK
return 0;
}
関連
-
[解決済み] string does not name a type Errorが発生するのはなぜですか?
-
[解決済み】IntelliSense:オブジェクトに、メンバー関数と互換性のない型修飾子がある
-
[解決済み】C++エラー:の初期化に一致するコンストラクタがありません。
-
[解決済み] 式はクラス型を持つ必要があります。
-
[解決済み】リンカーエラーです。"リンカ入力ファイルはリンクが行われていないため未使用"、そのファイル内の関数への未定義参照
-
[解決済み] 非静的データメンバの無効な使用
-
[解決済み】エラー:不完全な型へのメンバーアクセス:前方宣言の
-
[解決済み] 1ビットのセット、クリア、トグルはどのように行うのですか?
-
[解決済み] static_cast, dynamic_cast, const_cast, reinterpret_cast はいつ使うべきですか?
-
[解決済み] なぜ (int)x ではなく static_cast<int>(x) を使うのですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] テスト
-
[解決済み】C++エラー。アーキテクチャ x86_64 に対して未定義のシンボル
-
[解決済み】C++のGetlineの問題(オーバーロードされた関数 "getline "のインスタンスがない
-
[解決済み】C++ 式はポインタからオブジェクトへの型を持っている必要があります。
-
[解決済み】デバッグアサーションに失敗しました。C++のベクトル添え字が範囲外
-
[解決済み】エラー:strcpyがこのスコープで宣言されていない
-
[解決済み] 式はクラス型を持つ必要があります。
-
[解決済み】クラスのコンストラクタへの未定義参照、.cppファイルの修正も含む
-
[解決済み】変数やフィールドがvoid宣言されている
-
[解決済み】c++で.txtファイルから2次元の配列に読み込む