Cplusplus-cpp-polymorphism

提供:Dev Guides
移動先:案内検索

C ++の多態性

「多態性」という言葉は、多くの形式を持つことを意味します。 通常、ポリモーフィズムは、クラスの階層があり、それらが継承によって関連付けられている場合に発生します。

C ++ポリモーフィズムとは、メンバー関数を呼び出すと、その関数を呼び出すオブジェクトのタイプに応じて異なる関数が実行されることを意味します。

基本クラスが他の2つのクラスによって導出された次の例を考えてください-

#include <iostream>
using namespace std;

class Shape {
   protected:
      int width, height;

   public:
      Shape( int a = 0, int b = 0){
         width = a;
         height = b;
      }
      int area() {
         cout << "Parent class area :" <<endl;
         return 0;
      }
};
class Rectangle: public Shape {
   public:
      Rectangle( int a = 0, int b = 0):Shape(a, b) { }

      int area () {
         cout << "Rectangle class area :" <<endl;
         return (width *height);
      }
};

class Triangle: public Shape {
   public:
      Triangle( int a = 0, int b = 0):Shape(a, b) { }

      int area () {
         cout << "Triangle class area :" <<endl;
         return (width* height/2);
      }
};

//Main function for the program
int main() {
   Shape *shape;
   Rectangle rec(10,7);
   Triangle  tri(10,5);

  //store the address of Rectangle
   shape = &rec;

  //call rectangle area.
   shape->area();

  //store the address of Triangle
   shape = &tri;

  //call triangle area.
   shape->area();

   return 0;
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Parent class area :
Parent class area :

出力が正しくないのは、関数area()の呼び出しが、基本クラスで定義されたバージョンとしてコンパイラーによって一度設定されているためです。 これは、関数呼び出しの*静的解決*または*静的リンケージ*と呼ばれます。関数呼び出しは、プログラムが実行される前に修正されます。 area()関数はプログラムのコンパイル中に設定されるため、これは「初期バインディング」とも呼ばれます。

しかし、今、私たちのプログラムに少し変更を加えて、Shapeクラスのarea()の宣言の前にキーワード virtual を付けて、次のようにします-

class Shape {
   protected:
      int width, height;

   public:
      Shape( int a = 0, int b = 0) {
         width = a;
         height = b;
      }
      virtual int area() {
         cout << "Parent class area :" <<endl;
         return 0;
      }
};

このわずかな変更の後、前のサンプルコードがコンパイルされ実行されると、次の結果が生成されます-

Rectangle class area
Triangle class area

今回は、コンパイラーはポインターの型ではなく、ポインターの内容を調べます。 したがって、triクラスとrecクラスのオブジェクトのアドレスは* shapeに格納されるため、それぞれのarea()関数が呼び出されます。

ご覧のとおり、各子クラスには、関数area()の個別の実装があります。 これが、*多態性*の一般的な使用方法です。 同じ名前の関数、さらには同じパラメーターを持つ異なるクラスがありますが、実装は異なります。

仮想機能

*virtual* 関数は、キーワード *virtual* を使用して宣言された基本クラスの関数です。 派生クラスの別のバージョンを使用して、基本クラスで仮想関数を定義すると、この関数の静的リンケージが不要であることをコンパイラに通知します。

私たちが望んでいるのは、呼び出されるオブジェクトの種類に基づいて、プログラムの任意のポイントで呼び出される関数を選択することです。 この種の操作は、動的リンケージ、または*遅延バインディング*と呼ばれます。

純粋な仮想機能

仮想関数を基本クラスに含めて、そのクラスのオブジェクトに合わせて派生クラスで再定義できるようにすることもできますが、基本クラスの関数に指定できる意味のある定義はありません。 。

基本クラスの仮想関数area()を次のように変更できます-

class Shape {
   protected:
      int width, height;

   public:
      Shape(int a = 0, int b = 0) {
         width = a;
         height = b;
      }

     //pure virtual function
      virtual int area() = 0;
};

0は、関数にボディがなく、上記の仮想関数が pure virtual function と呼ばれることをコンパイラーに伝えます。