3

抽象クラスの目的は、開発者が基本クラスのオブジェクトを作成してからアップキャストできないようにすることではありませ

さて、アップキャストが必要なくても、私はまだそれを使用していますが、それは何らかの形で「不利」であることが証明されていますか?

より明確にする:
C ++での思考から:

多くの場合、設計では、基本クラスがその派生クラスのインターフェイスのみを提示するようにします。つまり、誰もが実際に基底クラスのオブジェクトを作成するのではなく、そのインターフェイスを使用できるようにアップキャストするだけです。これは、そのクラスを抽象化することで実現されます。

アップキャストとは、次のことを意味します。baseClass *obj = new derived ();

4

4 に答える 4

4

アップキャストは、非ポリモーフィッククラスでは不利になる可能性があります。例えば:

class Fruit { ... };  // doesn't contain any virtual method
class Apple : public Fruit { ... };
class Blackberry : public Fruit { ... };

それをどこかにアップキャストし、

Fruit *p = new Apple;  // oops, information gone

これで、(手動のメカニズムがなければ) ifがまたは*pのインスタンスであることを知ることはできません。AppleBlackberry

dynamic_cast<>[非ポリモーフィック クラスでは許可されないことに注意してください。]

于 2011-11-08T07:42:12.727 に答える
2

抽象クラスは、一連の (サブ) クラスに共通する概念を表現するために使用されますが、インスタンスを作成することは賢明ではありません。

クラスを考えてみましょうAnimal。動物だけのものは存在しないため、そのクラスのインスタンスを作成しても意味がありません。アヒル、イヌ、ゾウがあり、それぞれが動物のサブクラスです。animal クラスを正式に宣言することで、すべての種類の動物の類似性を捉えることができ、抽象化することでインスタンス化できないことを表現できます。

静的型付け言語でポリモーフィズムを利用するには、アップキャストが必要です。@Jigar Joshi がコメントで指摘したように、これはLiskov Substituion Principleと呼ばれます。

編集:アップキャストは不利ではありません。実際、コードを基本クラス (実装) ではなくスーパークラス (インターフェース) に依存させるように、可能な限りこれを使用する必要があります。これにより、後でコードを変更せずに実装を切り替えることができます。

于 2011-11-08T07:32:56.243 に答える
1

アップキャスティングは技術的なツールです。

すべてのツールと同様に、正しく使用すると便利ですが、一貫性を欠いて使用すると危険/不利になります。

特定のプログラミング パラダイムに関して、コードをどの程度「純粋」にしたいかによって、良い場合も悪い場合もあります。

現在、C++ は必ずしも「純粋な OOP」ではなく、必ずしも「純粋なジェネリック」でもなく、必ずしも「純粋な関数型」でもありません。また、C++ は「実用的な言語」であるため、「唯一無二のパラダイム」に適合させることは一般に有利ではありません。

技術的に言えば、

  • 派生クラスは、基本クラスにさらに何かを加えたものです
  • ベースポインターを介して派生を参照すると、派生スコープにジャンプするためのメカニズムがベースにない限り、その「何か」にアクセスできなくなります。
  • その暗黙的なジャンプのために C++ が提供するメカニズムは、仮想関数です。
  • C++ が提供する明示的なジャンプのメカニズムはdynamic_cast(ダウンキャストで使用されます) です。
  • 非ポリモーフィック オブジェクト (仮想メソッドを持たない) の場合static_cast(ダウンキャスト) は引き続き使用できますが、ランタイム チェックはありません。

長所と短所は、これらすべてのポイントを一緒に一貫して使用することと一貫性を欠いて使用することから派生します。ダウンキャストのみに関連する問題ではありません。

于 2011-11-08T08:01:50.983 に答える
0

1 つの欠点は、派生クラスで導入された新しい機能が明らかに失われることです。

class A
{
   void foo();
}

class B : public A
{
   void foo2();
}

A* b = new B;
b->foo2(); //error - no longer visible

ここでは、非仮想関数について話しています。

また、デストラクタを仮想化するのを忘れると、ベース オブジェクトへのポインタを介して派生オブジェクトを削除するときにメモリ リークが発生する可能性があります。

ただし、これらはすべて、優れたアーキテクチャで回避できます。

于 2011-11-08T07:41:06.527 に答える