web-dev-qa-db-ja.com

C ++継承のダウンキャスト

私の基本クラスは次のとおりです。

class point    //concrete class
{
 ...    //implementation
}

class subpoint : public point  //concrete class
{
...     //implementation
}

ポイントオブジェクトからサブポイントオブジェクトにキャストするにはどうすればよいですか?次の3つすべてを試しました。

point a;
subpoint* b = dynamic_cast<subpoint*>(&a);
subpoint* b = (subpoint*)a;
subpoint b = (subpoint)a;

これらのキャストの何が問題になっていますか?

16

ポイントオブジェクトからサブポイントオブジェクトにキャストするにはどうすればよいですか?

できません。 pointに変換演算子があるか、subpointに変換コンストラクタがない場合を除きます。この場合、キャストを必要とせずにオブジェクトタイプを変換できます。

参照されたオブジェクトが実際にあった場合、pointreference(またはポインター)からsubpointreference(またはポインター)にキャストできます。タイプsubpointの:

subpoint s;

point & a = s;
subpoint & b1 = static_cast<subpoint&>(a);
subpoint & b2 = dynamic_cast<subpoint&>(a);

最初 (static_cast)の方が危険です。変換が有効かどうかのチェックは行われないため、asubpointを参照しない場合は、b1の動作は未定義です。

二番目 (dynamic_cast)の方が安全ですが、pointが多態性である場合(つまり、仮想関数がある場合)のみ機能します。 aが互換性のないタイプのオブジェクトを参照している場合、例外がスローされます。

30
Mike Seymour

動的キャストの目的は、「オブジェクトが階層内の特定のタイプかどうかを実行時に確認する」ことです。それでは、あなたが持っているものを見てみましょう:

  1. ポイントオブジェクトがあります。サブポイントではありません。
  2. オブジェクトがサブポイントである場合、動的キャストを求めています。そうではありません。
  3. サブポイントではないため、dynamic_castは失敗します。そのオブジェクトが、キャストしようとしている型ではないことを通知する方法です。

対照的に、これはうまくいったでしょう:

subpoint c;
point *a = &c;
subpoint* b = dynamic_cast<subpoint*>(&a);
subpoint* b = (subpoint*)a;
5
Carl

最初の例では、_dynamic_cast_は、基本クラスに少なくとも1つの仮想メソッドがある場合にのみ機能します。また、オブジェクトが実際にキャストしようとしている型ではない場合、結果はNULLになります。

2番目の例では、aではなく_&a_が必要ですが、修正すると、オブジェクトタイプが間違っているため、未定義の動作が発生します。

3番目の例では、コピーの作成中に変換を行うために、pointoperator subpoint()メソッドが必要です。

3
Mark Ransom

全体として、pointsubpointではないため、これは機能しません。逆のみが真です。ただし、他にも問題があります。

順番に:


_subpoint* b = dynamic_cast<subpoint*>(&a);
_

_dynamic_cast_は、ポリモーフィック型、つまり少なくとも1つの仮想関数を宣言する型でのみ機能します。私の推測では、pointには仮想関数がないため、_dynamic_cast_では使用できません。


_subpoint* b = (subpoint*)a;
_

このキャストが機能するためには、pointが_subpoint *_への変換演算子を宣言する必要があります(例:point::operator subpoint *())。


_subpoint b = (subpoint)a;
_

このキャストが機能するためには、ポイントはsubpointへの変換演算子を宣言する必要がありますorsubpointは、pointから変換可能なパラメーターを取得するコンストラクターを持っている必要があります。

2
MSN

これらのキャストの何が問題になっていますか?

あなたがそれらをしようとするという事実。 pointsubpointではありません。うまくいったとしたら驚きます。

1
Luchian Grigore

asubpointにすることはできません。その実装はありません。

0
Daniel A. White