C++ 例によるポリモーフィズム
ポリモーフィズムとは何か C++?
In C++ポリモーフィズムにより、メンバー関数は、それを呼び出すオブジェクトに基づいて異なる動作をします。ポリモーフィズムは、多くの形式を持つことを意味するギリシャ語です。継承によって関連付けられたクラスの階層がある場合に発生します。
たとえば、関数 makeSound() があるとします。 猫がこの関数を呼び出すと、ニャーという音が鳴ります。 牛が同じ機能を呼び出すと、「モー」という音が鳴ります。
関数は XNUMX つありますが、状況が異なれば動作も異なります。 関数にはさまざまな形式があります。 したがって、ポリモーフィズムを達成しました。
多型の種類
C++ 2 種類のポリモーフィズムをサポートします。
- コンパイル時のポリモーフィズム、および
- 実行時のポリモーフィズム。
コンパイル時のポリモーフィズム
オーバーロードされた関数は、引数の数と型を一致させることで呼び出されます。情報はコンパイル時に存在します。つまり、 C++ コンパイラはコンパイル時に適切な関数を選択します。
コンパイル時のポリモーフィズムは、関数のオーバーロードと演算子のオーバーロードによって実現されます。
関数のオーバーロード
関数のオーバーロードは、名前は似ているが引数が異なる関数が多数ある場合に発生します。 引数は、数または型が異なる場合があります。
例
#include <iostream> using namespace std; void test(int i) { cout << " The int is " << i << endl; } void test(double f) { cout << " The float is " << f << endl; } void test(char const *ch) { cout << " The char* is " << ch << endl; } int main() { test(5); test(5.5); test("five"); return 0; }
出力:
コードのスクリーンショットは次のとおりです。
コードの説明:
- iostream ヘッダー ファイルをコードに含めます。 その機能を利用できるようになります。
- コードに std 名前空間を含めます。 呼び出さなくてもそのクラスを使用できるようになります。
- 整数パラメーター i を取る test という名前の関数を作成します。 { は関数テスト本体の始まりを示します。
- 上記の関数テストが呼び出された場合に実行されるステートメント。
- 上記の機能テストの本体は終了です。
- float パラメータ f を取る test という名前の関数を作成します。 { は関数テスト本体の始まりを示します。
- 上記の関数テストが呼び出された場合に実行されるステートメント。
- 上記の機能テストの本体は終了です。
- 文字パラメータ ch を受け取る test という名前の関数を作成します。 { は関数テスト本体の始まりを示します。
- 上記の関数テストが呼び出された場合に実行されるステートメント。
- 上記の機能テストの本体は終了です。
- main() 関数を呼び出します。 { は関数本体の始まりを示します。
- 関数 test を呼び出し、引数の値として 5 を渡します。 これにより、整数の引数を受け入れるテスト関数、つまり最初のテスト関数が呼び出されます。
- 関数 test を呼び出し、引数の値として 5.5 を渡します。 これにより、float 引数を受け入れるテスト関数、つまり XNUMX 番目のテスト関数が呼び出されます。
- 関数 test を呼び出し、引数の値として XNUMX を渡します。 これにより、文字引数を受け入れるテスト関数、つまり XNUMX 番目のテスト関数が呼び出されます。
- プログラムが正常に実行された場合、プログラムは値を返す必要があります。
- main() 関数の本体の終わり。
同じ名前で引数の種類が異なる XNUMX つの関数があります。 ポリモーフィズムを達成しました。
Operaトールのオーバーロード
In Operatorオーバーロードでは、 C++ 演算子です。また、演算子の動作も変わります。たとえば、2 つの文字列を連結する + 演算子を定義できます。これは、数値を加算する加算演算子として知られています。定義後、整数の間に配置すると、整数が加算されます。文字列の間に配置すると、文字列が連結されます。
例
#include<iostream> using namespace std; class ComplexNum { private: int real, over; public: ComplexNum(int rl = 0, int ov = 0) { real = rl; over = ov; } ComplexNum operator + (ComplexNum const &obj) { ComplexNum result; result.real = real + obj.real; result.over = over + obj.over; return result; } void print() { cout << real << " + i" << over << endl; } }; int main() { ComplexNum c1(10, 2), c2(3, 7); ComplexNum c3 = c1+c2; c3.print(); }
出力:
コードのスクリーンショットは次のとおりです。
コードの説明:
- その機能を使用するには、iostream ヘッダー ファイルをプログラムにインクルードします。
- std 名前空間を呼び出さずにそのクラスを使用するには、プログラムに std 名前空間を組み込みます。
- ComplexNum という名前のクラスを作成します。{ はクラス本体の始まりを示します。
- private アクセス修飾子を使用して、変数をプライベートとしてマークします。これは、変数がクラス内からのみアクセスできることを意味します。
- 実数とそれ以上の XNUMX つの整数変数を定義します。
- public アクセス修飾子を使用してコンストラクターを public としてマークします。これは、コンストラクターの外部からでもアクセスできることを意味します。 class.
- クラス コンストラクターを作成し、変数を初期化します。
- 変数 real の値を初期化します。
- 変数の値を初期化します。
- コンストラクター本体の終わり。
- + 演算子の意味をオーバーライドする必要があります。
- ComplexNum 型のデータ型結果を作成します。
- 複素数には + 演算子を使用します。この行は、ある数値の実部を別の数値の実部に追加します。
- 複素数には + 演算子を使用します。この行は、ある数値の虚数部を別の数値の虚数部に追加します。
- プログラムは、実行が成功すると変数 result の値を返します。
- + 演算子の新しい意味、つまりオーバーロードの定義はこれで終わりです。
- print() メソッドを呼び出します。
- 加算後の新しい複素数をコンソールに出力します。
- print()関数の本体の終わり。
- ComplexNum クラスの本体の終わり。
- main() 関数を呼び出します。
- 加算する実数部と複素数部の両方の値を渡します。c1 の最初の部分は c2 の最初の部分、つまり 10+3 に加算されます。c1 の 2 番目の部分は c の 7 番目の部分、つまり XNUMX+XNUMX に加算されます。
- オーバーロードされた + 演算子を使用して演算を実行し、結果を変数 c3 に格納します。
- 変数 c3 の値をコンソールに出力します。
- main() 関数の本体の終わり。
ランタイムポリモーフィズム
これは、オブジェクトのメソッドがコンパイル時ではなく実行時に呼び出されるときに発生します。 実行時のポリモーフィズムは、関数のオーバーライドによって実現されます。 呼び出される関数は実行時に確立されます。
関数のオーバーライド
関数のオーバーライドは、基本クラスの関数に派生クラスで新しい定義が与えられるときに発生します。 この時点で、基本関数はオーバーライドされたと言えます。
具体的な例を挙げますと、以下の通りです。
#include <iostream> using namespace std; class Mammal { public: void eat() { cout << "Mammals eat..."; } }; class Cow: public Mammal { public: void eat() { cout << "Cows eat grass..."; } }; int main(void) { Cow c = Cow(); c.eat(); return 0; }
出力:
コードのスクリーンショットは次のとおりです。
コードの説明:
- その機能を使用するには、iostream ヘッダー ファイルをプログラムにインポートします。
- std 名前空間を呼び出さずにそのクラスを使用するには、プログラムに std 名前空間を組み込みます。
- Mammal という名前のクラスを作成します。 { はクラス本体の始まりを示します。
- public アクセス修飾子を使用して、これから作成する関数をパブリックにアクセスできるように設定します。 このクラスの外部からアクセスできるようになります。
- Eat という名前のパブリック関数を作成します。 { は関数本体の始まりを示します。
- 関数 Eat() が呼び出されたときに cout 関数に追加されたステートメントを出力します。
- 関数eat()の本体の終わり。
- 哺乳類クラスの体の端。
- Mammal クラスを継承する Cow という名前のクラスを作成します。 Cow は派生クラスであり、Mammal は基本クラスです。 { はこのクラスの始まりを示します。
- public アクセス修飾子を使用して、これから作成する関数をパブリックにアクセスできるものとしてマークします。 このクラスの外部からアクセスできるようになります。
- 基本クラスで定義された関数 Eat() をオーバーライドします。 { は関数本体の始まりを示します。
- この関数が呼び出されたときにコンソールに出力されるステートメント。
- 関数 Eat() の本体の終わり。
- クラス Cow の本体の終わり。
- main() 関数を呼び出します。 { は、この関数の本体の始まりを示します。
- c. Cow クラスのインスタンスを作成し、名前を付けます。
- Cow クラスで定義された Eat() 関数を呼び出します。
- プログラムは正常に完了すると値を返す必要があります。
- main() 関数の終わり。
C++ 仮想機能
仮想関数は、実行時ポリモーフィズムを実装するもう一つの方法です。 C++これは、基本クラスで定義され、派生クラスで再定義される特別な関数です。仮想関数を宣言するには、virtual キーワードを使用する必要があります。キーワードは、基本クラスで関数の宣言の前に配置する必要があります。
仮想関数クラスが継承されると、仮想クラスはそのニーズに合わせて仮想関数を再定義します。 例えば:
#include <iostream> using namespace std; class ClassA { public: virtual void show() { cout << "The show() function in base class invoked..." << endl; } }; class ClassB :public ClassA { public: void show() { cout << "The show() function in derived class invoked..."; } }; int main() { ClassA* a; ClassB b; a = &b; a->show(); }
出力:
コードのスクリーンショットは次のとおりです。
コードの説明:
- iostream ヘッダー ファイルをコードに含めて、その機能を使用します。
- std 名前空間をコードに含めると、そのクラスを呼び出さずに使用できます。
- ClassA という名前のクラスを作成します。
- public アクセス修飾子を使用して、クラス メンバーをパブリックにアクセスできるものとしてマークします。
- show() という名前の仮想関数を作成します。 公的な行事となります。
- show()が呼び出されたときに印刷されるテキスト。endlは C++ 行の終了を意味するキーワード。マウス カーソルを次の行に移動します。
- 仮想関数 show() の本体の終わり。
- クラス ClassA の本体の終わり。
- クラス ClassA を継承する ClassB という名前の新しいクラスを作成します。 ClassA は基本クラスになり、ClassB は派生クラスになります。
- public アクセス修飾子を使用して、クラス メンバーをパブリックにアクセスできるものとしてマークします。
- 基本クラスで派生した仮想関数 show() を再定義します。
- 派生クラスで定義された show() 関数が呼び出されたときにコンソールに出力されるテキスト。
- show() 関数の本体の終わり。
- 派生クラス ClassB の本体の終わり。
- main() 関数を呼び出します。 プログラム ロジックは本体内に追加する必要があります。
- a という名前のポインター変数を作成します。 これは、ClassA という名前のクラスを指します。
- ClassB という名前のクラスのインスタンスを作成します。 インスタンスには b という名前が付けられます。
- アドレスbに格納されている値を変数aに代入します。
- 派生クラスで定義された show() 関数を呼び出します。 遅延バインディングが実装されました。
- main() 関数の本体の終わり。
コンパイル時のポリモーフィズムと実行時のポリモーフィズム
XNUMX つの主な違いは次のとおりです。
コンパイル時のポリモーフィズム | 実行時のポリモーフィズム |
---|---|
早期バインディングまたは静的多態性とも呼ばれます。 | 遅延/動的バインディングまたは動的ポリモーフィズムとも呼ばれます。 |
メソッドはコンパイル時に呼び出されます。 | メソッドは実行時に呼び出されます。 |
関数オーバーロードと演算子オーバーロードを介して実装 | メソッドのオーバーライドと仮想関数を介して実装されます。 |
例: メソッドのオーバーロード。 多くのメソッドは似たような名前を持っていますが、引数の数やタイプが異なります。 | 例: メソッドのオーバーライド。 多くのメソッドは、同様の名前と同じプロトタイプを持つ場合があります。 |
メソッドの検出はコンパイル時に行われるため、実行が高速化されます。 | メソッドディスカバリは実行時に実行されるため、実行が遅くなります。 |
Less コンパイル時にすべてがわかるため、問題解決の柔軟性が提供されます。 | メソッドは実行時に検出されるため、複雑な問題を解決するための柔軟性が大幅に向上します。 |
製品概要
- ポリモーフィズムとは、多くの形式を持つことを意味します。
- これは、継承を通じて関連するクラスの階層がある場合に発生します。
- ポリモーフィズムを使用すると、関数は、それを呼び出す/呼び出すオブジェクトに基づいて異なる動作をすることができます。
- コンパイル時ポリモーフィズムでは、呼び出される関数はコンパイル時に確立されます。
- 実行時ポリモーフィズムでは、呼び出される関数は実行時に確立されます。
- コンパイル時のポリモーフィズムは、関数のオーバーロードと演算子のオーバーロードによって決定されます。
- 関数のオーバーロードでは、名前は似ていても引数が異なる関数が多数存在します。
- パラメータの数やタイプは異なる場合があります。
- 演算子オーバーロードでは、新しい意味が定義されます。 C++ 演算子.
- 実行時のポリモーフィズムは、関数のオーバーライドによって実現されます。
- 関数オーバーライドでは、派生クラスは、基本クラスで定義された関数に新しい定義を与えます。