抽象クラスと純粋仮想関数を導入してみます。
つ・づ・き・ま~す・・・
ソーラー「次は
純粋仮想関数というものを導入してみたいとおもいます。」
マックス「さっき
仮想関数を導入したがそれと何か関係があるのか?」
ソーラー「かなり近い関係にあります。
親クラスGameCharacterのクラス宣言内
と
子クラスDragonのクラス宣言内で
同じ名前の
メンバ関数宣言
void statusDataDisplay();
が行われているとします。
つまり
親クラスGameCharacterのメンバ関数statusDataDisplay()
が
子クラスDragonのメンバ関数statusDataDisplay()
によって
🌞オーバーライド🌞
されているとします
でも ちょっとまって
このときの
親クラスGameCharacterのメンバ関数statusDataDisplay()は
💖仮想関数に設定されていないとします💖
オーバーライドがおこなわれているだけです
今までのエピソードをご覧になられてもお分かりになられますように
親クラスGameCharacter*型のポインタ変数宣言
GameCharacter* pta;
によって生成される
親クラスGameCharacter*型のポインタ変数
ptaに
子クラスDragon型のオブジェクト宣言
Dragon Pokky;
によって生成される
子クラスDragon型のオブジェクトPokkyのアドレス
🍋&Pokky🍋
を代入することができます
( 正確ではありませんが
まるで あたかも
親クラスGameCharacter*型のポインタ変数宣言
GameCharacter* pta;
によって生成される
親クラスGameCharacter*型のポインタ変数
ptaに
親クラスGameCharacter型のオブジェクトPokkyのアドレス
🍓&Pokky🍓
が代入されたような感じになります)
正確には
親クラスGameCharacter*型のポインタ変数宣言
GameCharacter* pta;
によって生成される
親クラスGameCharacter*型のポインタ変数
ptaに
子クラスDragon型のオブジェクトPokkyの(親クラスGameCharacterから引き継いだ)メンバ変数
Pokky.name
Pokky.HP
Pokky.MP
と
子クラスDragon型のオブジェクトPokkyの(親クラスGameCharacterから引き継いだ)メンバ関数
Pokky.statusDataDisplay()
の管理しているメモリ領域
を代表して管理しているアドレス
&Pokky
が代入されることになります
この状態で
pta->statusDataDisplay();
が実行されると
pta->statusDataDisplay()は
子クラスDragon型のオブジェクトPokkyの(親クラスGameCharacterから引き継いだ)メンバ関数
Pokky.statusDataDisplay()の管理するメモリ領域にアクセスすることになります
つまり
子クラスDragon型のオブジェクトPokkyの(親クラスGameCharacterから引き継いだ)メンバ関数
Pokky.statusDataDisplay();
が実行されることになります
そして
今度は
親クラスGameCharacterのクラス宣言内
の
メンバ関数宣言
void statusDataDisplay();
を
virtual void statusDataDisplay();
のように記述することにより
親クラスGameCharacterのメンバ関数
statusDataDisplay()
を
仮想関数に設定してみます
そして
子クラスDragonのクラス宣言内では
同じ名前statusDataDisplay()の
メンバ関数宣言
void statusDataDisplay();
を設定しておきます
(親クラスGameCharacterのメンバ関数statusDataDisplay()のオーバーライドを
子クラスDragonのメンバ関数statusDataDisplay()により行っています)
この状態で
親クラスGameCharacter*型のポインタ変数宣言
GameCharacter* pta;
によって生成される
親クラスGameCharacter*型のポインタ変数
ptaに
子クラスDragon型のオブジェクト宣言
Dragon Pokky;
によって生成される
子クラスDragon型のオブジェクトPokkyのアドレス
🍋&Pokky🍋
を代入したとします
この状態で
pta->statusDataDisplay();
を実行したとき
pta->statusDataDisplay()
は
子クラスDragon型のオブジェクトPokkyの(仮想関数である親クラスGameCharacterから引き継いだ)メンバ関数
Pokky.statusDataDisplay()
の管理するメモリ領域でなく
子クラスDragon型のオブジェクトPokkyの(オーバーライドしている子クラスDragonに元から備わっている)メンバ関数
Pokky.statusDataDisplay()
の管理するメモリ領域にアクセスすることになります
つまり
子クラスDragon型のオブジェクトPokkyの(オーバーライドしている子クラスDragonに元から備わっている)メンバ関数
Pokky.statusDataDisplay();
が実行されることになります
もう少し言い換えると
(オーバーライドしている子クラスDragonに元から備わっている)メンバ関数statusDataDisplay()の定義
👇
void Dragon::statusDataDisplay() {
cout << name << "\n";
cout << "HP " << HP << "\n";
cout << "MP " << MP << "\n";
cout << "DP " << DP << "\n";
}
👆内の
name
HP
MP
DP
に
子クラスDragon型のオブジェクトPokkyのメンバ変数
Pokky.name
Pokky.HP
Pokky.MP
Pokky.DP
が代入された
cout << Pokky.name << "\n";
cout << "HP " << Pokky.HP << "\n";
cout << "MP " << Pokky.MP << "\n";
cout << "DP " << Pokky.DP << "\n";
が実行されることになります
」
マックス「そ、そうだったな」
ソーラー「ここで
🌞純粋仮想関数🌞
の登場です。
親クラスGameCharacterのクラス宣言内
で
virtual void statusDataDisplay()=0;
のように
=0
を
くっつけると
statusDataDisplay()は
純粋仮想関数と呼ばれるものになります。」
マックス「純粋仮想関数と
仮想関数でなにか違いがあるのか?」
ソーラー「純粋がつくだけあって
本当に
statusDataDisplay()は
仮想の関数となるんです」
てんC「本当に仮想の関数になるのですか?」
ソーラー「そう、
なぜなら
純粋仮想関数は
関数の定義を記述しなくてもよい
(関数の定義を設定することはできるんですが)
からなんです。」
マックス「関数の定義がない関数??
そんな関数が存在するのか~~~い
何ですかあ
それはいったいど~いう関数なんだ」
ソーラー「親クラスGameCharacterの
😊仮想関数😊
statusDataDisplay()が
子クラスDragonのメンバ関数
statusDataDisplay()
によってオーバーライドされているとします
そして
親クラスGameCharacter&型の参照変数aに
子クラスDragon型のオブジェクトPokkyを代入したとします
このとき
参照変数aを用いて
a.statusDataDisplay()
を実行すると
オーバーライドの働きにより
参照変数aは
子クラスDragon型のオブジェクトPokkyの(子クラスに元から備わっている)メンバ関数
Pokky.statusDataDisplay()
の管理するメモリ領域にアクセスするのでしたね
つまり
子クラスDragon型のオブジェクトPokkyの(子クラスに元から備わっている)メンバ関数
Pokky.statusDataDisplay()
が実行さされることになります
このとき
子クラスに元から備わっているメンバ関数
statusDataDisplay()
の定義
👇
void Dragon::statusDataDisplay() {
cout << name << "\n";
cout << "HP " << HP << "\n";
cout << "MP " << MP << "\n";
cout << "DP " << DP << "\n";
}
👆
が用いられることになります
どうせ
親クラスGameCharacterのメンバ関数
statusDataDisplay()は仮想関数であり
子クラスに元から備わっているメンバ関数
statusDataDisplay()によって
オーバーライドされている状態では
子クラスに元から備わっているメンバ関数
statusDataDisplay()
の定義
が用いられるのなら
親クラスGameCharacterのメンバ関数
statusDataDisplay()
は何も定義されていなくてもいいとおもいませんか?」
マックス「まあ、確かに・・・」
新規登録で充実の読書を
- マイページ
- 読書の状況から作品を自動で分類して簡単に管理できる
- 小説の未読話数がひと目でわかり前回の続きから読める
- フォローしたユーザーの活動を追える
- 通知
- 小説の更新や作者の新作の情報を受け取れる
- 閲覧履歴
- 以前読んだ小説が一覧で見つけやすい
アカウントをお持ちの方はログイン
ビューワー設定
文字サイズ
背景色
フォント
組み方向
機能をオンにすると、画面の下部をタップする度に自動的にスクロールして読み進められます。
応援すると応援コメントも書けます