[訳]多態(二)


抽象ベースクラス
抽象ベースクラスは,我々の前の例のCPolygonクラスによく似ている.唯一の違いは、前の例ではCPolygonクラスのオブジェクト(polyなど)に対して最小限の機能を持つ有効な関数area()を定義したが、抽象ベースクラスではarea()メンバー関数に実装を提供することはできなかったことである.これは、関数宣言に「=0」を付けることで実現されます. 
抽象ベースクラスCPolygonは、次のようになります.
// abstract class CPolygon 

class CPolygon { 

  protected: 

    int width, height; 

  public: 

    void set_values (int a, int b) 

      { width=a; height=b; } 

    virtual int area () =0; 

};


この関数の実装の代わりにvirtual int area()に「=0」を加えたことに注意してください.このタイプの関数を純虚関数と呼び、少なくとも1つの純虚関数を含むクラスを抽象ベースクラスと呼ぶ. 
抽象ベースクラスと一般的なマルチステートクラスの主な違いは、抽象ベースクラスに少なくとも1つの実装が欠けているメンバーが存在するため、インスタンス化できないことである. 
しかし,オブジェクトをインスタンス化できないクラスは全く役に立たないわけではない.ポインタを作成し、そのマルチステート特性を利用することができます.したがって、次のように宣言します.
CPolygon poly;
オブジェクトをインスタンス化しようとしたため、宣言した抽象ベースクラスは無効です.ただし、次のようなポインタがあります.
CPolygon * ppoly1;
CPolygon * ppoly2;
完全に合法的です 
これでCPolygonは純粋な虚関数を含む以上,抽象ベースクラスである.いずれにしても、この抽象ベースクラスのポインタは、派生クラスのオブジェクトを指すために使用できます. 
ここでは完全な例です.
// abstract base class 

#include <iostream> 

using namespace std; 

 

class CPolygon { 

  protected: 

    int width, height; 

  public: 

    void set_values (int a, int b) 

      { width=a; height=b; } 

    virtual int area (void) =0; 

  }; 

 

class CRectangle: public CPolygon { 

  public: 

    int area (void) 

      { return (width * height); } 

  }; 

 

class CTriangle: public CPolygon { 

  public: 

    int area (void) 

      { return (width * height / 2); } 

  }; 

 

int main () { 

  CRectangle rect; 

  CTriangle trgl; 

  CPolygon * ppoly1 = &rect; 

  CPolygon * ppoly2 = &trgl; 

  ppoly1->set_values (4,5); 

  ppoly2->set_values (4,5); 

  cout << ppoly1->area() << endl; 

  cout << ppoly2->area() << endl; 

  return 0; 

}


出力:20 10
このプログラムを見直すと、同じタイプのポインタ(CPolygon*)で異なるオブジェクトにアクセスしていることがわかります.これはとても役に立ちます.たとえば、抽象ベースクラスCPolygonの関数メンバーを作成して、画面にarea()の結果を印刷します.CPolygonクラス自体にはこの関数の実装はありませんが、
// pure virtual members can be called 

// from the abstract base class 

#include <iostream> 

using namespace std; 

 

class CPolygon { 

  protected: 

    int width, height; 

  public: 

    void set_values (int a, int b) 

      { width=a; height=b; } 

    virtual int area (void) =0; 

    void printarea (void) 

      { cout << this.>area() << endl; } 

  }; 

 

class CRectangle: public CPolygon { 

  public: 

    int area (void) 

      { return (width * height); } 

  }; 

 

class CTriangle: public CPolygon { 

  public: 

    int area (void) 

      { return (width * height / 2); } 

  }; 

 

int main () { 

  CRectangle rect; 

  CTriangle trgl; 

  CPolygon * ppoly1 = &rect; 

  CPolygon * ppoly2 = &trgl; 

  ppoly1->set_values (4,5); 

  ppoly2->set_values (4,5); 

  ppoly1->printarea(); 

  ppoly2->printarea(); 

  return 0; 

}


出力:20 10
ダミーメンバーと抽象ベースクラスはC++マルチステート特性を与え,これによりオブジェクト向けのプログラミング手法が大規模なエンジニアリングにとってこのように有用になる.もちろん,これらの特性の非常に簡単な応用は見られたが,これらの特性はオブジェクト配列や動的に作成されたオブジェクトに用いることができる.
同じ例で終わりますが、このオブジェクトは動的に作成されます.
// dynamic allocation and polymorphism 

#include <iostream> 

using namespace std; 

 

class CPolygon { 

  protected: 

    int width, height; 

  public: 

    void set_values (int a, int b) 

      { width=a; height=b; } 

    virtual int area (void) =0; 

    void printarea (void) 

      { cout << this.>area() << endl; } 

  }; 

 

class CRectangle: public CPolygon { 

  public: 

    int area (void) 

      { return (width * height); } 

  }; 

 

class CTriangle: public CPolygon { 

  public: 

    int area (void) 

      { return (width * height / 2); } 

  }; 

 

int main () { 

  CPolygon * ppoly1 = new CRectangle; 

  CPolygon * ppoly2 = new CTriangle; 

  ppoly1->set_values (4,5); 

  ppoly2->set_values (4,5); 

  ppoly1->printarea(); 

  ppoly2->printarea(); 

  delete ppoly1; 

  delete ppoly2; 

  return 0; 

}


 
出力:20 10
 
原文:http://www.cplusplus.com/doc/tutorial/polymorphism/