ポリモーフィズム:インターフェースの複数の異なる実装はポリモーフィズムと呼ばれます。同じ操作が異なるオブジェクトに作用し、異なる解釈を持ち、異なる実行結果を生成する可能性があります。実行時に、派生クラスのメソッドは、基本クラスへのポインターを介して呼び出すことができます。
C ++では、ポリモーフィズムを実現するための次のメソッドがあります:仮想関数、抽象クラス、オーバーライド、テンプレート(注:オーバーロードはポリモーフィズムとは関係ありません)。
仮想キーワード:
コンパイラが実行中にvirtualキーワードを検出すると、動的バインディングに必要なメカニズムが自動的にインストールされます。まず、仮想関数を含むこれらのクラス(クラスのインスタンスではないことに注意してください)の場合、祖先クラスに仮想関数が含まれていても、それ自体いいえ-仮想関数テーブルVTABLEを作成します。これらの仮想関数テーブルでは、コンパイラはクラスの特定の仮想関数のアドレスを関数宣言の順序で配置します。同時に、このクラスのVTABLEを指す仮想関数を使用して、各クラスにvpointer(略してvptr)と呼ばれるポインターを配置します。
一般的に、オブジェクトのサイズはすべてのメンバー変数のサイズですが、仮想関数がある場合、クラスにメンバー変数がなくても、オブジェクトのサイズは0ではなく、仮想のサイズです。関数ポインタ。
親クラスの関数を仮想関数として定義する場合、サブクラス内の関数をオーバーロードし、親クラスポインターを使用してサブクラスオブジェクトをポイントし、関数を呼び出すと、親クラスの代わりにサブクラス関数が呼び出されます。親クラスの関数が仮想関数でない場合、親クラスの関数が呼び出されます
例を見てください:
//仮想メンバー
</pre><pre name="code" class="cpp"><span style="font-size:24px;">#include <iostream.h>
class CPolygon {
protected:
int width, height;
public:
void set_values (int a, int b) {
width=a;
height=b;
}
virtual int area (void) { return (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 poly;
CPolygon * ppoly1 = ▭
CPolygon * ppoly2 = &trgl;
CPolygon * ppoly3 = &poly;
ppoly1->set_values (4,5);
ppoly2->set_values (4,5);
ppoly3->set_values (4,5);
cout << ppoly1->area() << endl;
cout << ppoly2->area() << endl;
cout << ppoly3->area() << endl;
return 0;
}</span>
結果:
20100
これで、これら3つのクラス(CPolygon、CRectangle、CTriangle)はすべて同じメンバー(width、height、set_values()、area())を持ちます。area()は、後でサブクラスで改良されたため、仮想として定義されています。実験を行うことができます。コードでこのキーワード(仮想)を削除してからこのプログラムを実行すると、3つのポリゴンの面積計算結果はすべて20,10,0ではなく0になります。これは、キーワードvirtualがなく、プログラムの実行によって、対応するarea()関数(つまり、CRectangle :: area()、CTriangle :: area()、CPolygon :: area())が呼び出されなくなったためです。実際のオブジェクトの使用。代わりに、プログラムはすべてCPolygon :: area()を呼び出します。これは、これらの呼び出しがCPolygonタイプのポインターを介して行われるためです。したがって、キーワードvirtualの機能は、前の例に示すように、基本クラスのポインタを使用するときに、基本クラスと同じ名前のサブクラスのメンバーが適切なタイミングで呼び出されるようにすることです。
純粋仮想関数virtual()= 0
仮想関数の戻り値関数名(パラメーターリスト)= 0;
インターフェース関数はサブクラスによって実装されることになっています。このクラスのオブジェクトを作成できないように、クラスに純粋仮想関数を含めるにはどうすればよいですか。ただし、このクラスへのポインターは作成できます。
</pre><pre name="code" class="cpp">//virtual members
#include <iostream.h>
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 = ▭
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 *)を使用して、異なるタイプのオブジェクトをポイントします
抽象クラス:純粋仮想関数を持つクラス