はじめに
C++の継承において、子クラス(派生クラス)で親クラス(基底クラス)のメンバ関数をオーバーライドすると、子クラスのオブジェクトからは、デフォルトで子クラス側の関数が呼び出されます。
しかし、時には「子クラス独自の処理に加えて、親クラスが元々持っていた処理も実行したい」という場面があります。例えば、親クラスの表示機能に、子クラス独自の表示項目を追加したい、といったケースです。
このような場合、スコープ解決演算子 (::
) を使えば、子クラスの関数の中から、隠蔽されてしまった親クラスの同名関数を明示的に呼び出すことができます。
親クラスの関数を呼び出すサンプルコード
このコードは、Character
(親クラス)の displayStatus
関数を、Player
(子クラス)でオーバーライドします。そして、子クラス側の displayStatus
関数の中で、親クラスの displayStatus
関数を呼び出し、共通の表示処理を再利用します。
完成コード
#include <iostream>
#include <string>
using namespace std;
// --- 親クラス(基底クラス) ---
class Character {
public:
string name = "キャラクター";
int hp = 100;
virtual void displayStatus() {
cout << "--- Status ---" << endl;
cout << "名前: " << name << endl;
cout << "HP: " << hp << endl;
}
};
// --- 子クラス(派生クラス) ---
class Player : public Character {
public:
int level = 1;
// 親クラスのdisplayStatus関数をオーバーライド
void displayStatus() {
// 1. スコープ解決演算子(::)で、親クラスの同名関数を呼び出す
Character::displayStatus();
// 2. 子クラス独自の追加処理
cout << "レベル: " << level << endl;
cout << "--------------" << endl;
}
};
int main() {
Player myPlayer;
myPlayer.name = "勇者";
myPlayer.hp = 150;
myPlayer.level = 10;
// 子クラスでオーバーライドされた関数を呼び出す
myPlayer.displayStatus();
return 0;
}
実行結果
--- Status ---
名前: 勇者
HP: 150
レベル: 10
--------------
コードの解説
Character::displayStatus();
これが、オーバーライドされた親クラスの関数を呼び出すための核心部分です。
Character::
: スコープ解決演算子::
の前に親クラス名を指定します。displayStatus()
: 呼び出したい親クラスのメンバ関数名を記述します。
この一行により、Player
クラスの displayStatus
関数の中から、Character
クラスの displayStatus
関数を呼び出すことができます。実行結果を見ると、まず親クラスの表示処理(名前とHP)が実行され、その後に子クラス独自の表示処理(レベル)が追加されていることが分かります。
メリット
このテクニックを使えば、親クラスと子クラスに共通する処理を、親クラス側に一元化できます。もし、ステータス表示のヘッダー(--- Status ---
)のデザインを変更したくなっても、親クラスの関数を修正するだけで、全ての子クラスにその変更が反映されます。これにより、コードの重複が減り、保守性が大幅に向上します。
まとめ
今回は、子クラスでオーバーライドした関数の中から、スコープ解決演算子 ::
を使って親クラスの元の関数を呼び出す方法を解説しました。
- 構文は
親クラス名::関数名(引数)
- これにより、親クラスの機能を再利用しつつ、子クラスで機能を追加・拡張することができる。
オーバーライドは、単に親の機能を上書きするためだけのものではありません。このように親の機能を呼び出すことで、「基本機能は親に任せ、自分は差分の機能だけを実装する」という、効率的で美しい継承関係を築くことができます。