Menu
Coddy logo textTech

関数オーバーロード

CoddyのC++ジャーニー「オブジェクト指向プログラミング」セクションの一部 — レッスン 57/104。

関数オーバーロードを使用すると、同じ名前で異なるパラメータリストを持つ複数の関数を定義できます。コンパイラは、渡された引数に基づいて適切なバージョンを選択します。これは、コンパイル時ポリモーフィズムの主要な形式です。

オーバーロードを機能させるには、関数はそのシグネチャ(引数の数、型、またはその両方)が異なっている必要があります:

class Calculator {
public:
    int add(int a, int b) {
        return a + b;
    }
    
    double add(double a, double b) {
        return a + b;
    }
    
    int add(int a, int b, int c) {
        return a + b + c;
    }
};

Calculator calc;
calc.add(5, 3);        // add(int, int) を呼び出します
calc.add(2.5, 3.7);    // add(double, double) を呼び出します
calc.add(1, 2, 3);     // add(int, int, int) を呼び出します

コンパイラは各呼び出しを検証し、適切なオーバーロードに一致させます。これは完全にコンパイル時に行われるため、ランタイムオーバーヘッドは発生しません。

重要: 戻り値の型だけでは、オーバーロードされた関数を区別することはできません。以下はコンパイルエラーを引き起こします:

int getValue();
double getValue();  // エラー: 戻り値の型のみでオーバーロードすることはできません

関数オーバーロードにより、コードがより直感的になります。addIntsaddDoublesaddThreeInts のような個別の名前を作成する代わりに、1つの意味のある名前を使用し、残りの処理はコンパイラに任せることができます。

challenge icon

チャレンジ

簡単

関数のオーバーロードの威力を示すメッセージフォーマッタクラスを作成しましょう。複数の format() メソッドを持つ Formatter クラスを作成します。これらのメソッドは異なるタイプの入力を処理し、渡された引数に基づいてコンパイラが適切なバージョンを選択します。

コードは2つのファイルに分けて構成します:

  • Formatter.h: 異なるシナリオを処理する、オーバーロードされた format() メソッドを持つ Formatter クラスを定義します:
    • 1つの std::string を受け取り、次のように出力するメソッド: Message: <text>
    • std::stringint 型の優先度レベルを受け取り、次のように出力するメソッド: [Priority <priority>] <text>
    • std::stringdouble 型のタイムスタンプを受け取り、次のように出力するメソッド: [<timestamp>s] <text>
    • 3つの std::string パラメータ(送信者、受信者、メッセージ)を受け取り、次のように出力するメソッド: From <sender> to <receiver>: <message>
    すべてのメソッド名は format() とする必要があります。コンパイラは引数に基づいて正しいメソッドを選択します。
  • main.cpp: 4つの入力(それぞれ別の行)を読み取ります:
    1. シンプルなメッセージテキスト
    2. 優先度レベル(整数)
    3. タイムスタンプ(浮動小数点数)
    4. 送信者名

    Formatter オブジェクトを作成し、4つのオーバーロードされたメソッドすべてを実演します:

    • メッセージテキストのみを指定して format() を呼び出す
    • メッセージテキストと優先度を指定して format() を呼び出す
    • メッセージテキストとタイムスタンプを指定して format() を呼び出す
    • 送信者、受信者として "Admin"、およびメッセージテキストを指定して format() を呼び出す

例えば、入力が System ready312.5Server の場合:

Message: System ready
[Priority 3] System ready
[12.5s] System ready
From Server to Admin: System ready

同じメソッド名 format() を4回呼び出していますが、引数の型や数に基づいて、各呼び出しが異なるバージョンを呼び出していることに注目してください。これがコンパイル時ポリモーフィズムの動作です。コンパイラは、プログラムが実行される前に、どのオーバーロードを使用するかを決定します。

チートシート

関数オーバーロードを使用すると、同じ名前でパラメータリストが異なる複数の関数を定義できます。コンパイラは、コンパイル時に渡された引数に基づいて正しいバージョンを選択します。

関数は、そのシグネチャ(パラメータの数、型、またはその両方)が異なっている必要があります:

class Calculator {
public:
    int add(int a, int b) {
        return a + b;
    }
    
    double add(double a, double b) {
        return a + b;
    }
    
    int add(int a, int b, int c) {
        return a + b + c;
    }
};

Calculator calc;
calc.add(5, 3);        // add(int, int) を呼び出します
calc.add(2.5, 3.7);    // add(double, double) を呼び出します
calc.add(1, 2, 3);     // add(int, int, int) を呼び出します

重要: 戻り値の型だけでは、オーバーロードされた関数を区別することはできません:

int getValue();
double getValue();  // エラー: 戻り値の型のみでオーバーロードすることはできません

関数オーバーロードは、実行時のオーバーヘッドがないコンパイル時ポリモーフィズムの一形態です。

自分で試してみよう

#include <iostream>
#include <string>
#include "Formatter.h"

using namespace std;

int main() {
    // 入力を読み込む
    string message;
    getline(cin, message);
    
    int priority;
    cin >> priority;
    
    double timestamp;
    cin >> timestamp;
    cin.ignore();
    
    string sender;
    getline(cin, sender);
    
    // TODO: Formatter オブジェクトを作成する
    
    // TODO: メッセージテキストのみを指定して format() を呼び出す
    
    // TODO: メッセージテキストと priority を指定して format() を呼び出す
    
    // TODO: メッセージテキストと timestamp を指定して format() を呼び出す
    
    // TODO: sender、受信者として "Admin"、およびメッセージテキストを指定して format() を呼び出す
    
    return 0;
}
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

オブジェクト指向プログラミングのすべてのレッスン