親クラスに仮想関数を設定する場合は子クラスで同じ名前のメンバ関数を設定しオーバーライドされる必要があります
クラス宣言内のメンバ関数宣言にvirtualを設定するとそのメンバ関数は仮想関数となります
ソーラー「さて
親クラスGameCharacter*(アスタリスク)型のポインタ変数には
親クラスGameCharacter型のオブジェクトのアドレス
あるいは
子クラスDragon型のオブジェクトのアドレス
子クラスDragon*(アスタリスク)型のポインタ変数には
子クラスDragon型のオブジェクトのアドレスのみを
代入することができました
親クラスGameCharacter*(アスタリスク)型のポインタ変数ptaに
子クラスDragon型のオブジェクトPokkyのアドレスを代入した場合には
親クラスGameCharacter*(アスタリスク)型のポインタ変数ptaに
->(アロー演算子)を用いた
pta->statusDataDisplay()
は
子クラスDragon型のオブジェクトPokkyの(親クラスGameCharacterから引き継いだ)メンバ関数
Pokky.statusDataDisplay()
の管理するメモリ領域にアクセスすることになります
親クラスのメンバ関数statusDataDisplay()
が
子クラスのメンバ関数statusDataDisplay()
によって
🍋オーバーライドされていても🍋
親クラスGameCharacter*(アスタリスク)型のポインタ変数ptaに
子クラスDragon型のオブジェクトPokkyのアドレス&Pokkyを代入した場合については
親クラスGameCharacter*(アスタリスク)型のポインタ変数ptaに
->(アロー演算子)を用いた
pta->statusDataDisplay()
は
子クラスDragon型のオブジェクトPokkyの(子クラスに元から備わっている)メンバ関数
Pokky.statusDataDisplay()
の管理するメモリ領域にアクセスすることはできないんです
親クラスGameCharacter*(アスタリスク)型のポインタ変数ptaに
->(アロー演算子)を用いた
pta->(親クラスGameCharacterから引き継いだ)メンバ変数
pta->name
pta->HP
pta->MP
と
pta->(親クラスGameCharacterから引き継いだ)メンバ関数
pta->statusDataDisplay()
でアクセスできるのは
子クラスDragon型のオブジェクトPokkyの(親クラスGameCharacterから引き継いだ)メンバ変数
Pokky.name
Pokky.HP
Pokky.HP
と
子クラスDragon型のオブジェクトPokkyの(親クラスGameCharacterから引き継いだ)メンバ関数
Pokky.statusDataDisplay()
の管理しているメモリとなります
pta->statusDataDisplay();
が実行されると
子クラスDragon型のオブジェクトPokkyの(親クラスGameCharacterから引き継いだ)メンバ関数
Pokky.statusDataDisplay();
が実行されることになります
つまり
親クラスGameCharacter*(アスタリスク)型のポインタ変数ptaに
子クラスDragon型のオブジェクトPokkyのアドレスを代入した場合には
親クラスGameCharacter*(アスタリスク)型のポインタ変数ptaに
==============================================
子クラスDragon型のオブジェクトPokkyの(親クラスGameCharacterから引き継いだ)メンバ変数
Pokky.name
Pokky.HP
Pokky.HP
と
子クラスDragon型のオブジェクトPokkyの(親クラスGameCharacterから引き継いだ)メンバ関数
Pokky.statusDataDisplay()
==============================================
の管理しているメモリのアドレスが代入されているような状態となります
ですので
親クラスGameCharacter*(アスタリスク)型のポインタ変数ptaに
->(アロー演算子)を用いた
pta->(親クラスGameCharacterから引き継いだ)メンバ変数
pta->name
pta->HP
pta->MP
と
pta->(親クラスGameCharacterから引き継いだ)メンバ関数
pta->statusDataDisplay()
は
子クラスDragon型のオブジェクトPokkyの(親クラスGameCharacterから引き継いだ)メンバ変数
Pokky.name
Pokky.HP
Pokky.HP
と
子クラスDragon型のオブジェクトPokkyの(親クラスGameCharacterから引き継いだ)メンバ関数
Pokky.statusDataDisplay()
の管理しているメモリ
に
アクセスすることになります
さあ みなさん(^_^)/
仕組みがわかったかな。」
てんC「は~い🌞」
マックス「まあまあだ😊」
ソーラー「それでは
あらためまして
ptaの💖親クラスGameCharacter*型💖のポインタ変数宣言
GameCharacter* pta;
によって作製された
親クラスGameCharacter*型のポインタ変数
pta
に
Pokkyの子クラスDragon型のオブジェクト宣言
Dragon Pokky;
によって作製された
🍋子クラスDragon型🍋のオブジェクトPokkyのアドレス
&Pokky
が
pta=&Pokky;
と
代入された状態で
親クラスGameCharacter*型のポインタ変数ptaに
子クラスDragonのメンバ変数DPが用いられた
pta->DP=10;
親クラスGameCharacter*型のポインタ変数ptaに
親クラスGameCharacterのメンバ関数statusDataDisplay()を
オーバライドした
子クラスDragonのメンバ関数statusDataDisplay()が用いられた
pta->statusDataDisplay();
が実行できるかどうかを試してみたいと思います
そのプログラムはこちらです
👇
#include <iostream>
#include <string>//文字列を取り扱うためにヘッダファイル <string>をインクルードしています
using namespace std;
class GameCharacter {
public:
string name;
int HP;
int MP;
void statusDataDisplay();
};
void GameCharacter::statusDataDisplay() {
cout << name << "\n";
cout << "HP " << HP << "\n";
cout << "MP " << MP << "\n";
cout << "親クラスのメンバ関数statusDataDisplay()が実行されました" << "\n";
}
class Dragon :public GameCharacter {
public:
int DP;
void statusDataDisplay();
};
void Dragon::statusDataDisplay() {
cout << name << "\n";
cout << "HP " << HP << "\n";
cout << "MP " << MP << "\n";
cout << "DP " << DP << "\n";
cout << "子クラスのメンバ関数statusDataDisplay()が実行されました" << "\n";
}
int main() {
Dragon Pokky;
//👆Pokkyの子クラスDragon型のオブジェクト宣言をおこなっています
GameCharacter* pta;
pta = &Pokky;
pta->name = "ポッキー";
pta->HP = 15;
pta->MP = 5;
pta->DP = 7;
pta->statusDataDisplay();
return 0;
}
ビルド実行結果
重大度レベル コード 説明 プロジェクト ファイル 行 抑制状態
エラー (アクティブ) E0135 class "GameCharacter" にメンバー "DP" がありません Project33 c:\Users\solarplexuss\source\repos\Project33\Project33\Source.cpp 60
エラー C2039 'DP': 'GameCharacter' のメンバーではありません。 Project33 c:\users\solarplexuss\source\repos\project33\project33\source.cpp 60
ソーラー「
重大度レベル コード 説明 プロジェクト ファイル 行 抑制状態
エラー (アクティブ) E0135 class "GameCharacter" にメンバー "DP" がありません Project33 c:\Users\solarplexuss\source\repos\Project33\Project33\Source.cpp 60
エラー C2039 'DP': 'GameCharacter' のメンバーではありません。 Project33 c:\users\solarplexuss\source\repos\project33\project33\source.cpp 60
が表示されたね
今のプログラムでは
ptaの💖親クラスGameCharacter*型💖のポインタ変数宣言
GameCharacter* pta;
によって作製された
親クラスGameCharacter*型のポインタ変数
pta
に
Pokkyの子クラスDragon型のオブジェクト宣言
Dragon Pokky;
によって作製された
🍋子クラスDragon型🍋のオブジェクトPokkyのアドレス
&Pokky
が
pta=&Pokky;
と
代入されています
親クラスGameCharacterのクラス宣言内には
メンバ変数宣言
string name;
int HP;
int MP;
メンバ関数宣言
void statusDataDisplay();
は設定されていても
メンバ変数宣言
int DP;
は設定されていないので
親クラスGameCharacter*型のポインタ変数に
アロー演算子->を用いた
pta->name = "ポッキー";
pta->HP = 15;
pta->MP = 5;
pta->statusDataDisplay();
は実行できても
もちろん
pta->DP = 7;
を実行することはできません
そこで
プログラム内から
親クラスGameCharacter*型のポインタ変数
pta->に
子クラスDragonのメンバ変数DPが用いられた
pta->DP = 7;
を
取り除いたものを実行したら
pta->statusDataDisplay();
の実行結果はどのように表示されるかな?
そのプログラムはこちらです
👇
#include <iostream>
#include <string>//文字列を取り扱うためにヘッダファイル <string>をインクルードしています
using namespace std;
class GameCharacter {
public:
string name;
int HP;
int MP;
void statusDataDisplay();
};
void GameCharacter::statusDataDisplay() {
cout << name << "\n";
cout << "HP " << HP << "\n";
cout << "MP " << MP << "\n";
cout << "親クラスのメンバ関数statusDataDisplay()が実行されました" << "\n";
}
class Dragon:public GameCharacter {
public:
int DP;
void statusDataDisplay();
};
void Dragon::statusDataDisplay() {
cout << name << "\n";
cout << "HP " << HP << "\n";
cout << "MP " << MP << "\n";
cout << "DP " << DP << "\n";
cout << "子クラスのメンバ関数statusDataDisplay()が実行されました" << "\n";
}
int main() {
Dragon Pokky;
//👆Pokkyの子クラスDragon型のオブジェクト宣言をおこなっています
GameCharacter* pta;
pta = &Pokky;
pta->name = "ポッキー";
pta->HP = 15;
pta->MP = 5;
pta->statusDataDisplay();
return 0;
}
プログラムの実行結果
ポッキー
HP 15
MP 5
親クラスのメンバ関数statusDataDisplay()が実行されました
ソーラー「でてきました
プログラムの実行結果に表示されている
"親クラスのメンバ関数statusDataDisplay()が実行されました"
により
親クラスGameCharacter*型のポインタ変数pta->にstatusDataDisplay()が用いられた
pta->statusDataDisplay();
の実行においては
親クラスGameCharacterのメンバ関数statusDataDisplay()の定義が用いられているのがわかります
このプログラムのように
親クラスGameCharacterのメンバ関数statusDataDisplay()が
子クラスDragonのメンバ関数statusDataDisplay()によって
オーバーライドされていたとしても
親クラスGameCharacter*型のポインタ変数ptaに子クラスDragon型のオブジェクト
Pokkyのアドレスを代入し
親クラスGameCharacter*型のポインタ変数ptaにアロー演算子を用いた
pta->statusDataDisplay()
を実行した場合
子クラスDragon型のオブジェクトPokkyの(親クラスから引き継いだ)メンバ関数
Pokky.statusDataDisplay()
に相当するものが実行されることになります
子クラスDragon型のオブジェクトPokkyの(子クラスに元から備わっている)メンバ関数
Pokky.statusDataDisplay()
に相当するものが実行されることはありません
つまり
親クラスGameCharacter*型のポインタ変数ptaにアロー演算子を用いた
pta->statusDataDisplay()
は
子クラスDragon型のオブジェクトPokkyの(親クラスから引き継いだ)メンバ関数
Pokky.statusDataDisplay()
の管理しているメモリ領域に
アクセスすることはできても
子クラスDragon型のオブジェクトPokkyの(子クラスに元から備わっている)メンバ関数
Pokky.statusDataDisplay()
の管理しているメモリ領域に
アクセスすることはできないというわけです」
てんC「このプログラムでは
親クラスGameCharacter
のメンバ関数宣言は
void statusDataDisplay();
子クラスDragon
のメンバ関数宣言も
void statusDataDisplay();
に設定されています。
メンバ関数statusDataDisplay()のオーバーライドが行われていますが
機能していないようです
もしかして
なにかしらの意味があって
親クラスGameCharacterのクラス宣言内
の
メンバ関数statusDataDisplay()
と
同じ名前のメンバ関数statusDataDisplay()
を
子クラスDragonのクラス宣言内に設定する
オーバーライド
が設定されているのですか?」
ソーラー「そうなんです。
親クラスGameCharacter*型のポインタ変数
pta
に
子クラスDragon型のオブジェクトPokky
のアドレス
&Pokky
が代入された状態で
pta->statusDataDisplay();
が実行されると
子クラスDragon型のオブジェクト
Pokkyに
親クラスGameCharacterから引き継いだメンバ関数
statusDataDisplay()
が用いられた
子クラスDragon型のオブジェクトPokkyの(親クラスGameCharacterから引き継いだ)メンバ関数
Pokky.statusDataDisplay()
に相当する命令文が実行されることになります。
ですが
親クラスGameCharacter型のメンバ関数
statusDataDisplay()
と
子クラスDragon型のメンバ関数
statusDataDisplay()
を設定したのですから
pta->statusDataDisplay();
が実行されるとき
子クラスDragon型のオブジェクト
Pokkyに
子クラスDragonの(親クラスGameCharacterから引き継いだ)メンバ関数
statusDataDisplay()
が用いられた
子クラスDragon型のオブジェクトPokkyの(親クラスGameCharacterから引き継いだ)メンバ関数
Pokky.statusDataDisplay()
に相当する命令文が実行されるのではなく
子クラスDragon型のオブジェクト
Pokkyに
子クラスDragonの(子クラスDragonに元から備わっている)メンバ関数
statusDataDisplay()
が用いられた
子クラスDragon型のオブジェクトPokkyの(子クラスDragonに元から備わっている)メンバ関数
Pokky.statusDataDisplay()
に相当するものが
実行されるようにしたいときもあるというわけです。
どのようなときにそのような状況が生じてくるか?
詳しくは
仮想関数がどのように用いられるかをHuman(人間)型のゲームキャラクターに相手のステータスデータを読み取るスキャンという能力を設定することを通して学んでみましょう
の章をご覧ください」
マックス「そんな場合があるのか?
絶っっ対ないだろう
(そんなことはありません(笑)、すぐに身近なところで出てきます)
そもそも
親クラスGameCharacter*型のポインタ変数ptaでは
💖親クラスGameCharacterから引き継いだメンバ関数💖
statusDataDisplay()
をもちいた
pta->statusDataDisplay();
を実行できても
🍋子クラスDragonのメンバ関数🍋
statusDataDisplay()
をもちいた
pta->statusDataDisplay();
は実行できないんじゃないか
だから
pta->statusDataDisplay();
が実行されるとき
子クラスDragon型のオブジェクト
Pokkyに
子クラスDragonの(親クラスGameCharacterから引き継いだ)メンバ関数
statusDataDisplay()
が用いられた
子クラスDragon型のオブジェクトPokkyの(親クラスGameCharacterから引き継いだ)メンバ関数
Pokky.statusDataDisplay()
に相当する命令文が実行されるのではなく
子クラスDragon型のオブジェクト
Pokkyに
子クラスDragonの(子クラスDragonに元から備わっている)メンバ関数
statusDataDisplay()
が用いられた
子クラスDragon型のオブジェクトPokkyの(子クラスDragonに元から備わっている)メンバ関数
Pokky.statusDataDisplay()
に相当するものが
実行されるなんてのは無理だろう
」
ソーラー「そうなんです。
今のプログラムのように
親クラスGameCharacterのクラス宣言内で
メンバ関数宣言
void statusDataDisplay();
子クラスDragonのクラス宣言内で
メンバ関数宣言
void statusDataDisplay();
が実行されているとします
このように
親クラスGameCharacterのクラス宣言内と子クラスDragonのクラス宣言内で
同じ名前のメンバ関数宣言
void statusDataDisplay();
が設定されているとします
また メンバ関数のオーバーライドのお話に戻りますが
子クラスDragon型のオブジェクト宣言
Dragon Pokky;
を実行すると
🌞子クラスDragon型のオブジェクト🌞
Pokky
が生成されます。
そして
子クラスDragonに元から備わっているメンバ関数
statusDataDisplay()
が用いられた
子クラスDragon型のオブジェクトの(子クラスDragonに元から備わっている)メンバ関数
Pokky.statusDataDisplay()
を実行することができます
もちろん
Pokky.statusDataDisplay();
が実行されると
子クラスDragonのメンバ関数
statusDataDisplay()
の定義がもちいられることになります。
親クラスと子クラスで
同じ名前のメンバ関数
が設定されている
イコール
😊オーバーライドされていると😊
子クラス型のオブジェクトを作製した際
親クラスのメンバ関数でなく
子クラスのメンバ関数が用いられた
子クラス型のオブジェクトのメンバ関数
だけが実行できることになります。
オーバーライドされた
親クラスのメンバ関数の定義が用いられるということはありません
ですが
そうなんですが
子クラスDragon*型でなく
親クラスGameCharacter*型のポインタ変数
pta
に
子クラスDragon型のオブジェクトPokky
のアドレス
&Pokky
が代入された場合に
親クラスGameCharacter*型のポインタ変数
pta->statusDataDisplay();
が実行されたなら
子クラスDragonに元から備わっているメンバ関数statusDataDisplay()の定義が用いられた
pta->statusDataDisplay();
(Dragon.statusDataDisplay();)
が実行されるようにしたいというわけです。」
マックス「ふ~ん、
そんな場合があるのか?」
再び・・・ 予告です
詳しくは
仮想関数がどのように用いられるかをHuman(人間)型のゲームキャラクターに相手のステータスデータを読み取るスキャンという能力を設定することを通して学んでみましょう
の章をご覧ください
そのような例が身近に登場してきます
solarplexussより
ソーラー「
そこで
そのためには
親クラスGameCharacterのクラス宣言
class GameCharacter {
public:
string name;
int HP;
int MP;
void statusDataDisplay();
};
内の
メンバ関数宣言
void statusDataDisplay();
に
virtualをつけて
virtual void statusDataDisplay();
として
親クラスGameCharacterのメンバ関数
statusDataDisplay()
を
😊仮想関数😊
に設定します。
(😊無かったことにするという意味合いがあります 、(笑)😊)
そうすると
親クラスGameCharacter*のポインタ変数
pta
に
子クラスDragon型のオブジェクトPokky
のアドレス
&Pokky
を代入して
pta->statusDataDisplay();
を実行すると
子クラスDragon型のオブジェクトPokkyに
親クラスGameCharacterから引き継いだメンバ関数
statusDataDisplay()
が用いられた
子クラスDragon型のオブジェクトPokkyの(親クラスGameCharacterから引き継いだ)メンバ関数
Pokky.statusDataDisplay();
に相当するものが実行されるのではなく
子クラスDragon型のオブジェクト
Pokkyに
🍋子クラスDragonに元から備わっているメンバ関数🍋
statusDataDisplay()
が用いられた
子クラスDragon型のオブジェクトPokkyの(子クラスDragonに元から備わっている)メンバ関数
Pokky.statusDataDisplay();
が実行されることになります。
そのことを示す次のプログラムをご覧ください。
#include <iostream>
#include <string>//文字列を取り扱うためにヘッダファイル <string>をインクルードしています
using namespace std;
class GameCharacter {
public:
string name;
int HP;
int MP;
virtual void statusDataDisplay();//👈👈👈🌞statusDataDisplay()を仮想関数に設定しました
};
void GameCharacter::statusDataDisplay() {
cout << name << "\n";
cout << "HP " << HP << "\n";
cout << "MP " << MP << "\n";
cout << "親クラスのメンバ関数statusDataDisplay()が実行されました" << "\n";
}
class Dragon :public GameCharacter {
public:
int DP;
void statusDataDisplay();
};
void Dragon::statusDataDisplay() {
cout << name << "\n";
cout << "HP " << HP << "\n";
cout << "MP " << MP << "\n";
cout << "DP " << DP << "\n";
cout << "子クラスのメンバ関数statusDataDisplay()が実行されました" << "\n";
}
int main() {
Dragon Pokky;
//👆Pokkyの子クラスDragon型のオブジェクト宣言をおこなっています
GameCharacter* pta;
pta = &Pokky;
pta->name = "ポッキー";
pta->HP = 15;
pta->MP = 5;
pta->statusDataDisplay();
return 0;
}
プログラムの実行結果
ポッキー
HP 15
MP 5
子クラスのメンバ関数statusDataDisplay()が実行されました
マックス「プログラムの実行結果が
親クラスのメンバ関数statusDataDisplay()が実行されました
だったのが
子クラスのメンバ関数statusDataDisplay()が実行されました
に
入れ替わった!
virtualを設定しただけなのに
親クラスのメンバ関数statusDataDisplay()が実行されました
の代わりに
子クラスのメンバ関数statusDataDisplay()が実行されました
が表示されている!」
ソーラー「このように
親クラスのクラス宣言内の
メンバ関数宣言にvirtualを設定すると
そのメンバ関数は
仮想関数と呼ばれるものになります。
そして
親クラスGameCharacter*のポインタ変数
pta
に
子クラスDragon型のオブジェクトPokky
のアドレス
&Pokky
を代入した状態で
pta->statusDataDisplay();
が実行されると
子クラスDragon型のオブジェクト
Pokkyに
仮想関数である
親クラスGameCharacterから引き継いだメンバ関数
virtual void statusDataDisplay()
が用いられた
pta->statusDataDisplay();
が実行されるのではなく
いいかえると
親クラスGameCharacterから引き継いだメンバ関数
virtual void statusDataDisplay()
が用いられた
子クラスDragon型のオブジェクトPokkyのメンバ関数
Pokky.statusDataDisplay();
に相当するものが実行されるのではなく
オーバーライドがおこり
子クラスDragon型のオブジェクトPokky
に
🍋子クラスDragonに元から備わっているメンバ関数🍋
statusDataDisplay()
が用いられた
子クラスDragon型のオブジェクトPokkyの(子クラスDragonに元から備わっている)メンバ関数
Pokky.statusDataDisplay();
に相当するものが実行されることになります
つまり
まとめると
親クラスGameCharacter*のポインタ変数
pta
に
子クラスDragon型のオブジェクトPokky
のアドレス
&Pokky
を代入した状態で
pta->statusDataDisplay();
を実行した場合
通常できないはずの
子クラスDragon型のオブジェクトPokkyに
子クラスDragonに元から備わっているメンバ関数が用いられた
Pokky.statusDataDisplay()
が実行されることになるんです
どう 😊
ただし
親クラスGameCharacterのメンバ関数
statusDataDisplay()
が
同じ名前の
子クラスDragonのメンバ関数
statusDataDisplay()
によってオーバーライドされている必要があります
そして
🌞ここが重要なのですが🌞
たとえ
💖仮想関数が設定されていても💖
親クラスGameCharacter*のポインタ変数
pta
に
🍋子クラスDragon型🍋のオブジェクトPokky
のアドレス
&Pokky
が代入された場合は
親クラスGameCharacter*のポインタ変数
pta
にアロー演算子を用いた
pta->name
pta->HP
pta->MP
と
親クラスGameCharacterのメンバ関数statusDataDisplay()
をオーバーライドしている
子クラスDragonのメンバ関数statusDataDisplay()の定義が用いられた
pta->statusDataDisplay()
を実行することはできますが
子クラスDragonに元から備わっているメンバ変数
DP
が用いられた
pta->DP
や
(もし設定されていれば)
子クラスDragonだけに元から備わっているメンバ関数
が用いられた
pta->子クラスDragonだけに元から備わっているメンバ関数
を実行することはできません
ですので
もし
プログラム内で
pta->に子クラスDragonのメンバ変数DPが用いられた
pta->DP
が記述されていると
ビルドエラーが表示されることになります
そのプログラムはこちらです
👇
#include <iostream>
#include <string>//文字列を取り扱うためにヘッダファイル <string>をインクルードしています
using namespace std;
class GameCharacter {
public:
string name;
int HP;
int MP;
virtual void statusDataDisplay();//🌞statusDataDisplay()が仮想関数が設定されています
};
void GameCharacter::statusDataDisplay() {
cout << name << "\n";
cout << "HP " << HP << "\n";
cout << "MP " << MP << "\n";
cout << "親クラスのメンバ関数statusDataDisplay()が実行されました" << "\n";
}
class Dragon :public GameCharacter {
public:
int DP;
void statusDataDisplay();
};
void Dragon::statusDataDisplay() {
cout << name << "\n";
cout << "HP " << HP << "\n";
cout << "MP " << MP << "\n";
cout << "DP " << DP << "\n";
cout << " 子クラスのメンバ関数statusDataDisplay()が実行されました" << "\n";
}
int main() {
Dragon Pokky;
//👆Pokkyの子クラスDragon型のオブジェクト宣言をおこなっています
GameCharacter* pta;
pta=&Pokky;
pta->name = "ポッキー";
pta->HP = 15;
pta->MP = 5;
pta->DP = 7;
pta->statusDataDisplay();
return 0;
}
プログラムの実行結果
エラー C2039 'DP': 'GameCharacter' のメンバーではありません。
エラー (アクティブ) E0135 class "GameCharacter" にメンバー "DP" がありません
ソーラー「このプログラムでも
Dragon Pokky;
GameCharacter* pta;
pta=&Pokky;
の実行により
親クラスGameCharacter*型のポインタ変数
pta
に
子クラスDragon型のオブジェクトPokky
のアドレス
&Pokky
が代入されていますが
親クラスGameCharacter*のポインタ変数
pta
にアロー演算子を用いた
親クラスGameCharacterのメンバ変数
pta->name
pta->HP
pta->MP
と
親クラスGameCharacterのメンバ関数statusDataDisplay()
をオーバーライドしている
子クラスDragonのメンバ関数statusDataDisplay()の定義が用いられた
pta->子クラスDragonのメンバ関数statusDataDisplay()
のみ
が実行できることになります
親クラスGameCharacter*のポインタ変数
pta
にアロー演算子を用いた
子クラスDragonのメンバ変数
pta->DP
を実行することはできません
pta->name = "ポッキー";
pta->HP = 15;
pta->MP = 5;
pta->DP = 7;
pta->statusDataDisplay();
のうち
pta->name = "ポッキー";
pta->HP = 15;
pta->MP = 5;
pta->statusDataDisplay();
は実行することができますが
pta->DP = 7;
は実行することができないので
ビルドエラーが表示されることになります」
マックス「まあ、そりゃそうだろう
なんてったって
ptaは
💖親クラスGameCharacter*のポインタ変数💖
だからな
pta->
につづけて用いることができるのは
親クラスGameCharacterのメンバ変数
name
HP
MP
親クラスGameCharacterのメンバ関数
statusDataDisplay()
だけってわけだ
まあ
pta->statusDataDisplay();
が実行されると
親クラスGameCharacterのメンバ関数
statusDataDisplay()
は仮想関数に設定されているので
子クラスDragonのメンバ関数の定義がもちいられることになるがな
うひゃは なんか理解した」
新規登録で充実の読書を
- マイページ
- 読書の状況から作品を自動で分類して簡単に管理できる
- 小説の未読話数がひと目でわかり前回の続きから読める
- フォローしたユーザーの活動を追える
- 通知
- 小説の更新や作者の新作の情報を受け取れる
- 閲覧履歴
- 以前読んだ小説が一覧で見つけやすい
アカウントをお持ちの方はログイン
ビューワー設定
文字サイズ
背景色
フォント
組み方向
機能をオンにすると、画面の下部をタップする度に自動的にスクロールして読み進められます。
応援すると応援コメントも書けます