C++マニアック

オーバーロード,オーバーライド,関数のシグニチャ,overload,override,signature

ページの末尾へ   トップページ > オーバーロードとオーバーライド

TOPIC  節電しましょう。電力の使用状況グラフ(東電)

オーバーロードとオーバーライド

オーバーロードとオーバーライドはどちらも関数に関することですが、これらは似ているようで、全く異なるものです。ここでは、これについて解説します。

  1. 関数のシグニチャ
  2. オーバーロード
  3. 演算子のオーバーロード
  4. オーバーライド
  5. まとめ
  6. オーバーロード関連本

関数のシグニチャ ページの先頭へ

オーバーロードとオーバーライドを理解するには、まず、関数のシグニチャ(signature)について知る必要があります。関数のシグニチャとは、関数名と、関数の引数の型の並び方の組み合わせのことです。例えば、次の関数で考えてみましょう。

float Function(int iParam1, double dParam2) const {
    return iParam1 + dParam2;
}

関数名と引数の部分の型の並び方、Function, int, double と、もしあれば const がシグニチャということになります。シグニチャには、関数の戻り値の型は関係ないので、上記の例では float はシグニチャの一部ではありません

オーバーロード ページの先頭へ

オーバーロードは、日本語で書けば、関数の多重定義です。関数のオーバーロードとはシグニチャは異なるが同じ名前の関数が複数定義されることで、例えば、次のように同じ名前の複数の関数を定義できます。

int    SameName(int iValue)               { return iValue;          }  // @
double SameName(double dValue)            { return dValue;          }  // A
float  SameName(int iValue, float fValue) { return iValue + fValue; }  // B
void   SameName(void)                     {                         }  // C

関数の呼び出し時には、引数に与えられたオブジェクトの型によってどの関数が呼び出されるかが決定されます。例えば、次のようになります。

int main() {
    int    iValue = 0;
    double dValue = 0.0;
    float  fValue = 0.0f;
    SameName(iValue);           // @が呼び出されます。
    SameName(dValue);           // Aが呼び出されます。
    SameName(iValue, fValue);   // Bが呼び出されます。
    SameName();                 // Cが呼び出されます。
    return 0;
}

オーバーロードのサンプル Overload1.cpp

演算子のオーバーロード ページの先頭へ

演算子のオーバーロードについては、オペレータのオーバーロード をご覧ください。

オーバーライド ページの先頭へ

関数のオーバーライドとは、日本語で書けば、関数の上書き、または、差し替えというべきものです。これは、クラスが継承されるときに、派生クラスで基本クラスのメンバ関数と同じシグニチャの関数を定義することによって行われます。通常シグニチャの同じ関数は、同じクラスのメンバ関数として定義したり、グローバル関数として定義すると二重定義エラーになってしまいますが、クラスが継承されているときには、その基本クラスと派生クラスで同じシグニチャの関数を定義できます。派生クラスを使用するときには、派生クラスのメンバ関数が優先的に使用されます。このことを、基本クラスのメンバ関数が、派生クラスのメンバ関数でオーバーロードされたと言うわけです。

class CBase {
public:
    double GetdValue(int iValue) { return iValue; }     // 基本クラスの関数
};

// 上記クラスを継承するクラス
class CDerived : public CBase {
public:
    float GetdValue(int iValue) { return iValue * 2; }  // 継承クラスの関数
};

int main() {
    CDerived derived;
    double dValue1 = derived.GetdValue(2);               // 継承クラスの関数が使用される。
    double dValue2 = derived.CBase::GetdValue(2);       // 明示すれば、ベースクラスの関数が使用できる。
    printf("dValue1 = %f, dValue2 = %f\n", dValue1, dValue2);
    return 0;
}

上記の例の結果は次のようになります。

dValue1 = 4.000000, dValue2 = 2.000000

オーバーライドのサンプル Override1.cpp

まとめ ページの先頭へ

関数のオーバーロードとオーバーライドの差を端的にまとめると次のようになります。

  • オーバーロードではグローバル関数またはクラスのメンバ関数として、シグニチャは異なるが同じ名前の関数が複数定義されます。
  • オーバーライドでは基本クラスと派生クラスで、シグニチャが同じ(当然名前も同じ)複数の関数が定義されます。