オーバーライドとは
クラスを継承する際、基本クラスのメンバ関数を派生クラスで上書きすることが出来ます。
これをオーバーライドと言います。
継承についてはクラスの継承を参照。
使い方は簡単です。
派生クラス内で基本クラスと同じ型と名前を持った関数を定義するだけです。
例を見てみましょう。
override_sample1.cpp
class Basis { int a; void set(int x) { a = x; } void print() { std::cout << a << endl; } }; class Derivation : public Basis { int b; void set(int x) { b = x; } };
基本クラスBasisを継承した派生クラスDerivationで関数set()をオーバーライドしています。
その為、Derivationのインスタンスからset()を呼び出すとbが初期化されます。
print()はオーバーライドしていないので呼び出すとaが表示されます。
Basisのset()を呼び出したい場合もありますね。
その場合は「::」(スコープ解決演算子)を使ってクラスを明示します。
override_sample2.cpp
Derivation d; d.set(0); d.Basis::set(0);
2行目がDerivationのset()、3行目がBasisのset()を呼び出します。
オーバーライドとオーバーロード
突然ですがオーバーロードを覚えているでしょうか。
オーバーライドと名前が似ていますが別物です。
同名で引数が異なる関数を定義するのがオーバーロード、
同名の関数を上書きするのがオーバーライドです。
詳しくはデフォルト引数と関数のオーバーロードを参照。
ここでオーバーライドの際、引数を変えることが出来ます。
ですがそうしてしまうと基本クラスの関数が引数を変えた派生クラスの関数で上書きされてしまい、基本クラスの関数を呼び出すとエラーとなってしまいます。
これはusing句を使って解決します。
派生クラス内で以下の内容を記述することで基本クラスの関数を使うことを明示します。
using 【基本クラス名】::【メンバ関数名】;
上記の例でset()を残したい場合は以下のようになります。
using Basis::set;
これによってDerivationのset()の引き数を変えることができます。
継承とコンストラクタ、デストラクタ
補足の説明となりますが、継承した際のコンストラクタ、デストラクタの扱いについてです。
派生クラスを呼び出した場合、基本クラスのコンストラクタが呼び出され、その後派生クラスのコンストラクタが呼び出されます。
派生クラスが破棄されるときは、派生クラスのデストラクタが呼び出された後に基本クラスのデストラクタが呼び出されます。
ただし、その際呼び出されるのは引数のないデフォルトコンストラクタです。
基本クラスの引数付きコンストラクタを呼び出したい場合は、派生クラスのコンストラクタ内で明示的に呼び出す必要があります。