overload と override と hiding

これは, C++プログラマであるかを見分ける10の質問 - Life like a clown の 「overload と override と hiding の違いについて説明せよ」と言う質問に対する回答的な記事です.これらの差については,本の虫: C++におけるoverloadとoverrideとhiding 辺りでうまく纏まっているので引用して終わります.

同じ名前で、他のシグネチャの違う関数セットのことを、関数のオーバーロード(overload)という。

void f(int);
void f(double);

Derived classがBase classと同じvirtual関数を宣言しているとき、Derived classのvirtual関数は、Base classの同virtual関数を、オーバーライド(override)しているという。

struct Base
{
    virtual void f() {}
};

struct Derived : Base
{
    virtual void f() {} // override
};

Derived classのメンバー名に対し、同名のBase classのメンバーがある場合、Derived classのメンバーは、Base classのメンバーを隠している(hiding)という。

struct Base
{
    void f(int);
    int value;
};

struct Derived : Base
{
    void f(double);
    double value;
};

int main()
{
    Derived d;

    d.f(0); // void Derived::f(dobule)を呼ぶ
    d.value; // double Derived::valueである
}

結局これは、Derived classスコープのメンバーである名前が、Base classスコープのメンバーの名前を隠しているに過ぎない。同じことは、クラス以外のスコープでも起こる。

本の虫: C++におけるoverloadとoverrideとhiding

overload と override の違いは様々な所でよく言われるので分かると思いますが,C++ では*1これらの他に hiding と言うものが存在します.C++ において,メンバ関数を override するためには基底クラスの該当メンバ関数が virtual 宣言されていなくてはなりませんが,virtual 宣言されていなくても一見すると override されているような挙動を示します.これが hiding になります.

override と hiding の違いは,基底クラスのポインタで操作を行うような場合に問題になってきます.virtual 宣言のなされたメンバ関数は基底クラスのポインタから該当のメンバ関数を呼び出しても継承先クラスの override したメンバ関数の挙動を示しますが,virtual 宣言されていないメンバ関数の場合は基底クラスの挙動を示します.このような違いがあるので,問題となっているクラスがインターフェース的な使われた方をする場合は特に,注意して使用する必要があります.

*1:別に C++ 以外のプログラミング言語でもありそうですが.