/ / newを使った暗黙のダウンキャストですか? - C ++、継承、新演算子、派生クラス、ダウンキャスト

新しいOKを使用して暗黙的にダウンキャスティングしていますか? - c ++、継承、new-operator、派生クラス、ダウンキャスト

このC ++コードについてどう思いますか。

Polygon* p;
if(shape=="Rectangle")
p = new Rectangle();
else if(shape=="Triangle")
p = new Triangle();
else
exit(EXIT_FAILURE);

RectangleとTriangleは、基本クラスのPolygonから派生しています。

その背後にある考え方は、私は特定のを使用する必要があるということですプログラムが実行されるまで、必要なクラスを知らなくても、派生クラスからメソッドを取得できます。 これを行うより良い方法はありますか?コンパイルはできますが、選択した派生クラスのデストラクタが呼び出されて特定の変数が正しく解放されるようになるのではないかと思います。

補助的な質問:dynamic_cast操作にはデータコピーが含まれますか。

ありがとう:)

編集:

これらの非常に有益な回答をありがとうございました。

それでは、メソッドを言ってみましょう

bool isIsosceles()

Triangleでは実装されていますが、Rectangleでは実装されていません。

それからすぐに電話をかける

p->isIsosceles()

明らかに失敗するでしょう。

私の最初のアイデアは以下のいずれかです。

基本クラスPolygonの仮想メソッドとしてisIsosceles()を宣言して実装します。

virtual bool isIsosceles()
{
cout << "Isosceles means nothing to me." << endl;
exit(EXIT_FAILURE);
}

またはifステートメントでdynamic_castを使用する。

これらのオプションのどれかがここで良い習慣ですか?

どうもありがとう

回答:

回答№1は1

覚えていれば動作します delete p とのデストラクタ Polygonvirtual。これは重要です。

より良い代替手段は、スマートポインタにまとめることです。


回答№2の場合は1

newを使用した暗黙のダウンキャストは問題ありませんか?

ここでは "荒廃"することはありません。これは、多態性の振る舞いの直接的な使い方です。きみの Polygon * 基本クラスへのポインタです。あなたの構築コードは、仮想メンバ関数の使用を通して実装を抽象化するオブジェクトを生成します。

コンパイルはできますが、選択した派生クラスのデストラクタが呼び出されて特定の変数が正しく解放されるようになるのではないかと思います。

基底クラス内のデストラクタが仮想クラスであるとすれば、基底クラスポインタを通してオブジェクトを解放することですべてが正しく行われます。

delete p;

これを行うより良い方法はありますか?

あなたは使うことができます std::unique_ptr<Polygon> あなたの削除プロセスを自動化する Polygon オブジェクトスマートポインタを使用すると、ポインタが範囲外になったときにオブジェクトが破壊されます。

ありません dynamic_cast 操作はデータコピーを含みますか?

私はあなたがのための使用を持っていないと仮定しています dynamic_cast ここに Polygon 関心のあるすべての操作に対して仮想メンバー関数を宣言します。しかし、あなたがするとき dynamic_castデータのコピーは行われていません。システムはキャストが許可されているかどうかを確認し、正しくキャストされたポインタを取得するか、または nullptr.


回答№3の場合は0

これはダウンキャストではありません。ここでは実際にポリモーフィズムを使用しています。つまり、基本型のオブジェクトとして使用する派生型のオブジェクトを作成します。

あなたはそれをすることができます、しかしあなたがnewで割り当てるすべてのものと同じように、deleteを使ってください。もう1つ注意すべきことは、仮想デストラクタが必要なことです。 Polygon、そのように:

class Polygon {

virtual ~Polygon();
}

それ以外の場合は、オブジェクトのスライスが発生してしまいます。つまり、オブジェクトが「半削除」されます。

追加の注意:参考までに、ダウンキャストは、あなたのクラスを使って、以下のことを行います。

Polygon* polygon = new Triangle();

Triangle* triangle = dynamic_cast<Triangle*>(polygon);

// Check that we effectively had a triangle under this polygon pointer
if(triangle){
//do something with the triangle
}

回答№4の場合は0

その背後にある考え方は、プログラムが実行されるまでどのクラスが必要かを知らずに、派生クラスの特定のメソッドを使用する必要があるということです。

そのような種類は多態性の目的を無効にします。これにより、どの派生型を処理しているかを知らなくても操作を実行できます。

これを行うより良い方法はありますか?

それはあなたが実際に何をしようとしているかによって異なりますそもそも成し遂げる。あなたが示したものは、例えばクラスファクトリの一部として実装することができます。しかし、それらを作成した後にそれらのオブジェクトをどのように使用しているのかを示していないので、正しいことをしているかどうかはわかりません。

特定の変数が適切に解放されるように、選択された派生クラスのデストラクタが呼び出されるのでしょうか。

場合に限ります ~Polygon() として宣言されています virtual.

dynamic_cast操作にはデータのコピーが含まれますか?

いや dynamic_cast 同じオブジェクトに対してVMTの別のセクションへのポインタを取得するために、単にランタイムルックアップを実行します。