C++/override
overrideキーワードの概要
[編集]C++11から導入されたoverride
指定子は、派生クラスで基底クラスの仮想関数をオーバーライドする際に使用します。この指定子を関数定義に記述することで、その関数が確かに基底クラスの仮想関数をオーバーライドしていることをコンパイラに明示的に指示します。override
キーワードの主な目的は、誤ったオーバーライドを防ぎ、コードの可読性とメンテナンス性を向上させることにあります。
仮想関数とオーバーライド
[編集]オーバーライドは、クラス継承の中核概念の1つです。基底クラスで宣言された仮想関数は、派生クラスでオーバーライド(再定義)することができます。
// 基底クラス class Base { public: virtual void foo() { /* ... */ } }; // 派生クラス class Derived : public Base { public: void foo() override { /* ... */ } // ここでオーバーライド };
overrideキーワードの使用例
[編集]override
キーワードを使うことで、関数がオーバーライドであることを明示できます。
class Base { public: virtual void foo(int x) { /* ... */ } virtual void bar(double x, double y) { /* ... */ } }; class Derived : public Base { public: void foo(int x) override { /* ... */ } // OK // void bar(double x) override { /* ... */ } // エラー! 引数の個数が異なる };
上の例では、Derived::bar
はBase::bar
をオーバーライドしようとしていますが、引数の個数が異なるためにコンパイルエラーになります。
overrideキーワードの利点
[編集]- コンパイラのチェック
override
キーワードを使うと、コンパイラが基底クラスの仮想関数との一致をチェックします。引数の型や個数が異なる場合や、仮想関数ではない関数をオーバーライドしようとした場合にエラーを出します。このようなミスを事前に検出でき、バグの発生を防げます。- 可読性の向上
override
キーワードを使うと、その関数がオーバーライドであることが明示的に分かるので、コードの可読性が上がります。誰が見ても関数の役割を一目で把握できます。- メンテナンス性の向上
- 基底クラスの仮想関数の名前や引数を変更した際、
override
キーワードを使っていると、そのオーバーライドがコンパイルエラーになります。こうすることで、影響を受ける派生クラスのコードを見つけるのが簡単になります。
overrideキーワードの注意点
[編集]- 仮想関数でないメンバ関数にはつけられない
override
キーワードは、仮想関数でない通常の非仮想関数にはつけられません。そのような関数にoverride
指定子を付けた場合、コンパイルエラーになります(これは本質的に利点です)。- 基底クラスの関数と完全に一致する必要がある
- オーバーライドする関数は、基底クラスの仮想関数の名前、引数の型と個数、
const
修飾などが完全に一致している必要があります。一つでも異なるとコンパイルエラーになります。
ベストプラクティス
[編集]オーバーライドする仮想関数には必ずoverride
指定子を付けることが推奨されています。これにより、コードの保守性が格段に上がります。派生クラスで仮想関数をオーバーライドしたつもりが、実際には新しい関数を導入してしまったというミスを防ぐことができます。また、将来的に基底クラスの関数シグネチャが変更された際の影響を受けるコードを見つけやすくなります。
プロジェクト内ですべてのクラスがこのルールに従うよう、ガイドラインとして明記し徹底するのがベストプラクティスです。
まとめ
[編集]override
キーワードは、派生クラスで基底クラスの仮想関数をオーバーライドする際に使用する指定子です。誤ったオーバーライドを防ぎ、コードの安全性と可読性を高める役割があります。可能な限りoverride
指定子を付けるべきであり、それがC++のベストプラクティスと言えるでしょう。オーバーライドのミスを事前に検出でき、コードの保守性が格段に向上します。