C++
 Computer >> コンピューター >  >> プログラミング >> C++

C++のポリモーフィズム(多態性)とは?関数オーバーロードを使った実例付き解説

ポリモーフィズム(多態性)は、オブジェクト指向プログラミングにおける最も重要な概念の一つで、「同じインターフェースが複数の異なる形を取る」ことを意味します。

C++では、ポリモーフィズムは大きく次の2種類に分類されます。

  • コンパイル時ポリモーフィズム:関数オーバーロードや演算子オーバーロードが代表例です。どの関数を呼び出すかはコンパイル時に決定されます。
  • 実行時ポリモーフィズム:仮想関数(virtual関数)による関数オーバーライドが代表例です。実際に呼び出される関数は実行時に決定されます。

この記事では、その中でも分かりやすい関数オーバーロードを使ったコンパイル時ポリモーフィズムのサンプルコードを紹介します。

サンプルコード

#include <iostream>
using namespace std;
class Example {
    public :
    void func(int a) {
        cout << "\nThe value of a: " << a;
    }
    void func(int a, int b) {
        cout << "\nThe value of a: " << a;
        cout << "\nThe value of b: " << b;
    }
    void func(char c) {
        cout << "\nThe value of c: " << c;
    }
};
int main() {
    Example obj;
    cout<< "\nOne int value";
    obj.func(5);
    cout<< "\nOne char value";
    obj.func('A');
    cout<< "\nTwo int values";
    obj.func(7, 2);
    return 0;
}

実行結果

上記プログラムの出力は以下の通りです。

One int value
The value of a: 5
One char value
The value of c: A
Two int values
The value of a: 7
The value of b: 2

プログラムの解説

それでは、このプログラムの仕組みを順番に見ていきましょう。

1. 関数のオーバーロード部分

クラスExample内では、メンバ関数func()がオーバーロードされています。引数の型や個数が異なる3つのfunc()関数が定義されており、呼び出し時の引数に応じて適切なものが自動的に選択されます。

class Example {
    public :
    void func(int a) {
        cout << "\nThe value of a: " << a;
    }
    void func(int a, int b) {
        cout << "\nThe value of a: " << a;
        cout << "\nThe value of b: " << b;
    }
    void func(char c) {
        cout << "\nThe value of c: " << c;
    }
};

ここで定義されているのは、以下の3種類です。

  • func(int a):int型の引数を1つ受け取る
  • func(int a, int b):int型の引数を2つ受け取る
  • func(char c):char型の引数を1つ受け取る

コンパイラは、呼び出し時に渡された引数の型と個数を照合し、最も一致する関数をコンパイル時に選択します。これがコンパイル時ポリモーフィズムの正体です。

2. main()関数での呼び出し部分

main()関数内では、クラスExampleのオブジェクトobjを生成し、func()を異なる引数で何度も呼び出すことで、関数オーバーロードの動作を確認しています。

int main() {
    Example obj;
    cout<< "\nOne int value";
    obj.func(5);
    cout<< "\nOne char value";
    obj.func('A');
    cout<< "\nTwo int values";
    obj.func(7, 2);
    return 0;
}
  • obj.func(5) → 引数がint型1つなので func(int) が呼ばれる
  • obj.func('A') → 引数がchar型なので func(char) が呼ばれる
  • obj.func(7, 2) → 引数がint型2つなので func(int, int) が呼ばれる

このように、同じ名前の関数でも引数によって異なる処理を実行できるのが、関数オーバーロードによるポリモーフィズムの利点です。コードの可読性が向上し、呼び出し側は関数名を意識せずに済むため、直感的なAPI設計が可能になります。

  1. C++で解く最大消去値(Maximum Erasure Value)― スライディングウィンドウによる効率的な実装

    正の整数からなる配列が与えられたとき、すべての要素が一意(重複なし)である部分配列を1つだけ消去することを考えます。この操作で得られるスコアは、消去した部分配列の要素の総和です。ここでの目的は、ちょうど1つの部分配列を消去したときに得られる最大の合計値を返すことです。なお、配列 arr が a の部分配列であるとは、a[l], a[l+1], …, a[r] という形で表される連続した部分列と一致することを意味します。入力例と出力例例1arr[ ] = { 1, 2, 4, 5, 6 }出力:17説明: 最適な部分配列は {2, 4, 5, 6} です。その総和は 17 になります。例2arr

  2. C++で学ぶ式ツリー(Expression Tree)の基本と具体例

    式ツリーとは何か式ツリー(Expression Tree)とは、二分木の一種であり、木の各ノードが「演算子」または「オペランド(被演算子)」のいずれかで構成される特殊なデータ構造です。数式を木構造として表現することで、コンパイラや電卓アプリなどが数式を効率的に解析・評価できるようになります。ノードの役割式ツリーにおける各ノードは、次のように役割が分かれています。葉ノード(リーフノード):オペランド(数値や変数)を表します。非葉ノード(内部ノード):演算子(+、-、*、/ など)を表します。つまり、計算の対象となる値は必ず葉に配置され、それらをどのように処理するかを示す演算子が親ノードとして上に