🌻天国にいけるC++言語入門🌻 進化し続けるオブジェクト指向プログラミング ver3.2307
親クラスアスタリスク*型のポインタ変数に子クラス型のオブジェクトのアドレスを代入するということは単純に親クラス型のオブジェクトのアドレスを代入していると捉えることができます
ですので 親クラスアスタリスク*型のポインタ変数に子クラス型のオブジェクトのアドレスを代入をしたり親クラス&型の参照変数に子クラス型のオブジェクトを代入することができます
親クラスアスタリスク*型のポインタ変数に子クラス型のオブジェクトのアドレスを代入するということは単純に親クラス型のオブジェクトのアドレスを代入していると捉えることができます
ソーラー「
前のエピソードで見てきたように
親クラスアスタリスク*型のポインタ変数には
親クラス型のオブジェクトのアドレス
あるいは
子クラス型のオブジェクトのアドレス
子クラスアスタリスク*型のポインタ変数には
子クラス型のオブジェクトのアドレスのみを
代入することができました
では
親クラスアスタリスク*型のポインタ変数に
🌞子クラス型のオブジェクトのアドレスが代入されたとき🌞
の
プログラムをご覧ください
👇
#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()が実行されました
ソーラー「このプログラムでは
ptaの💖親クラスGameCharacter*型💖のポインタ変数宣言
GameCharacter* pta;
によって作製された
親クラスGameCharacter*型のポインタ変数
pta
に
Pokkyの子クラスDragon型のオブジェクト宣言
Dragon Pokky;
によって作製された
🍋子クラスDragon型🍋のオブジェクトPokkyのアドレス
&Pokky
が
pta=&Pokky;
と
代入されています。」
マックス「???
子クラスDragon*型のポインタ変数
pta
に
Pokkyの子クラスDragon型のオブジェクト宣言
Dragon Pokky;
によって作製された
🍋子クラスDragon型🍋のオブジェクトPokkyのアドレス
&Pokky
が
pta=&Pokky;
と
代入されているんじゃないのか~」
ソーラー「いいえ
💖親クラスGameCharacter*型💖のポインタ変数
pta
に
Pokkyの子クラスDragon型のオブジェクト宣言
Dragon Pokky;
によって作製された
🍋子クラスDragon型🍋のオブジェクトPokkyのアドレス
&Pokky
が
pta=&Pokky;
と
代入されています。」
マックス「???
親クラスGameCharacter*型のポインタ変数
pta
に
🍋子クラスDragon型🍋のオブジェクトPokkyのアドレス
&Pokky
が
pta=&Pokky;
と
代入された状態で
pta->name = "ポッキー";
pta->HP = 15;
pta->MP = 5;
pta->statusDataDisplay();
を実行したのか
親クラスGameCharacterのメンバ変数宣言
string name;
int HP;
int MP;
親クラスGameCharacterのメンバ関数宣言
void statusDataDisplay();
を
子クラスDragonのクラス宣言内に継承してはいるんだが・・・
子クラスDragonのクラス宣言内には
オーバーライドされている同じ名前のメンバ関数宣言
void statusDataDisplay();
があるだろう?
pta->statusDataDisplay();
を実行すると
子クラスDragonのメンバ関数statusDataDisplay()の定義がもちいられて
プログラムの実行結果
ポッキー
HP 15
MP 5
子クラスのメンバ関数statusDataDisplay()が実行されました
が表示されるとおもうんだが・・・
プログラムの実行結果をみると・・・
pta->statusDataDisplay();
を実行するときは
親クラスGameCharacterのメンバ関数statusDataDisplay()の定義がもちいられているじゃないか
???
🍋子クラスDragon型🍋のオブジェクトPokkyのアドレス
&Pokky
が
親クラスGameCharacter*型のポインタ変数
pta
に
代入されたんだろう?
pta->statusDataDisplay();
を実行するときは
子クラスDragonのメンバ関数statusDataDisplay()の定義がもちいられるんじゃないのか?
よくわからん?????」
ソーラー「そうですね
Pokkyの親クラスGameCharacter型のオブジェクト宣言
GameCharacter Pokky;
の実行によって
親クラスGameCharacter型のオブジェクトPokkyが作製された場合
親クラスGameCharacter型のオブジェクトPokkyのメンバ変数
Pokky.name
Pokky.HP
Pokky.MP
親クラスGameCharacter型のオブジェクトPokkyのメンバ関数
Pokky.statusDataDisplay()
が生成されることになります
このとき
親クラスGameCharacter型のオブジェクトPokkyのメンバ変数
Pokky.name
Pokky.HP
Pokky.MP
が管理しているメモリ領域と
親クラスGameCharacter型のオブジェクトPokkyのメンバ関数
Pokky.statusDataDisplay()
が管理しているメモリ領域が存在していることになります
このとき
親クラスGameCharacter*型のポインタ変数宣言
GameCharacter* pta;
を実行して
親クラスGameCharacter*型のポインタ変数
pta
を作製します
親クラスGameCharacter型のオブジェクトPokkyのアドレス&Pokkyを
親クラスGameCharacter*型のポインタ変数
pta
に
pta=&Pokky;
と代入します
親クラスGameCharacter*型のポインタ変数
ptaにアロー演算子->を用いた
pta->name
pta->HP
pta->MP
pta->statusDataDisplay()
は
親クラスGameCharacter型のオブジェクトPokkyのメンバ変数
Pokky.name
Pokky.HP
Pokky.MP
親クラスGameCharacter型のオブジェクトPokkyのメンバ関数
Pokky.statusDataDisplay()
と
同じ働きをすることになりました
親クラスGameCharacter*型のポインタ変数ptaにアロー演算子->を用いた
pta->name
pta->HP
pta->MP
pta->statusDataDisplay()
は
親クラスDragon型のオブジェクトPokkyのメンバ変数
Pokky.name
Pokky.HP
Pokky.MP
が管理しているメモリ領域と
親クラスGameCharacter型のオブジェクトPokkyのメンバ関数
Pokky.statusDataDisplay()
が管理しているメモリ領域
にアクセスすることになります
親クラスGameCharacter*型のポインタ変数ptaに
親クラスGameCharacter型のオブジェクトPokkyのアドレス&Pokky
代入したので
親クラスGameCharacter*型のポインタ変数ptaにアロー演算子->を用いた
pta->name
pta->HP
pta->MP
pta->statusDataDisplay()
は
親クラスGameCharacter型のオブジェクトPokkyのメンバ変数
Pokky.name
Pokky.HP
Pokky.MP
が管理しているメモリ領域と
親クラスGameCharacter型のオブジェクトPokkyのメンバ関数
Pokky.statusDataDisplay()
が管理しているメモリ領域
にアクセスすることになったわけです
つまり
親クラスGameCharacter型のオブジェクトPokkyのメンバ変数
Pokky.name
Pokky.HP
Pokky.MP
が管理しているメモリ領域と
親クラスGameCharacter型のオブジェクトPokkyのメンバ関数
Pokky.statusDataDisplay()
が管理しているメモリ領域
を代表しているアドレスが
親クラスGameCharacter型のオブジェクトPokkyのアドレス&Pokky
で
そのアドレス&Pokkyを格納するのが
親クラスGameCharacter*型のポインタ変数ptaなんです
もっといえば
親クラスGameCharacter型のオブジェクトPokkyのメンバ変数
Pokky.name
Pokky.HP
Pokky.MP
が管理しているメモリ領域と
親クラスGameCharacter型のオブジェクトPokkyのメンバ関数
Pokky.statusDataDisplay()
が管理しているメモリ領域
は
あるメモリ領域を占有しています」
マックス「お、おもしろいな・・・😊
それは当たり前のことすぎるんじゃないか?」
ソーラー「ここがとても重要なポイントなんです
親クラスGameCharacter型のオブジェクトPokkyのメンバ変数
Pokky.name
Pokky.HP
Pokky.MP
が管理しているメモリ領域と
親クラスGameCharacter型のオブジェクトPokkyのメンバ関数
Pokky.statusDataDisplay()
が管理しているメモリ領域
は
あるメモリ領域を占有していますが
それらのメモリをまとめて
ある変数が管理しているととらえると
それらのメモリを代表するアドレスもあるわけで
その変数のアドレスを格納する
その(変数の型)アスタリスク*型のポインタ変数も
登場してくることになります」
マックス「まあ、そうなるんじゃないか?」
ソーラー「このことはのちに生きていくことになるんだ
みんな おぼえておいてほしいな」
マックス「なんだ・・・
べつにそんなに特別の話でもないような・・
オーソドックスなパターンじゃないか
親クラスGameCharacter*型のポインタ変数ptaは
親クラスGameCharacter型のオブジェクトPokkyのメンバ変数
Pokky.name
Pokky.HP
Pokky.MP
が管理しているメモリ領域と
親クラスGameCharacter型のオブジェクトPokkyのメンバ関数
Pokky.statusDataDisplay()
が管理しているメモリ領域
にアクセスできるってわけだ」
ソーラー「そうなんです
それとは別に
Pokkyの🍋子クラスDragon型🍋のオブジェクト宣言
Dragon Pokky;
の実行によって
子クラスDragon型のオブジェクトPokkyが作製された場合
子クラスDragon型のオブジェクトPokkyの(親クラスから引き継いだ)メンバ変数
Pokky.name
Pokky.HP
Pokky.MP
子クラスDragon型のオブジェクトPokkyの(親クラスから引き継いだ)メンバ関数
Pokky.statusDataDisplay()
さらに
子クラスDragon型のオブジェクトPokkyの(子クラスに元から備わっている)メンバ変数
Pokky.DP
子クラスDragon型のオブジェクトPokkyの(子クラスに元から備わっている)メンバ関数
Pokky.statusDataDisplay()
が生成されることになります」
マックス「さっきの場合より
この部分が
👇
子クラスDragon型のオブジェクトPokkyの(子クラスに元から備わっている)メンバ変数
Pokky.DP
子クラスDragon型のオブジェクトPokkyの(子クラスに元から備わっている)メンバ関数
Pokky.statusDataDisplay()
👆
が増えた感じだな」
ソーラー「そうなんです
Pokkyの💖親クラス型GameCharacter型💖のオブジェクト宣言
GameCharacter Pokky;
を実行して
親クラス型GameCharacter型のオブジェクトPokkyを作製した場合と
Pokkyの🍋子クラスDragon型🍋のオブジェクト宣言
Dragon Pokky;
を実行して
子クラスDragon型のオブジェクトPokkyを作製した場合の違いってわけなんです
このとき
子クラスDragon型のオブジェクトPokkyの(親クラスから引き継いだ)メンバ変数
Pokky.name
Pokky.HP
Pokky.MP
子クラスDragon型のオブジェクトPokkyの(親クラスから引き継いだ)メンバ関数
Pokky.statusDataDisplay()
が管理しているメモリ領域
と
子クラスDragon型のオブジェクトPokkyの(子クラスに元から備わっている)メンバ変数
Pokky.DP
子クラスDragon型のオブジェクトPokkyの(子クラスに元から備わっている)メンバ関数)
Pokky.statusDataDisplay()
が存在していることになります
🌞同じ名前の🌞
子クラスDragon型のオブジェクトPokkyの(親クラスから引き継いだ)メンバ関数
Pokky.statusDataDisplay()
と
子クラスDragon型のオブジェクトPokkyの(子クラスに元から備わっている)メンバ関数
Pokky.statusDataDisplay()
が
生成されているところが
🌞ポイントです🌞
🌞同じ名前だけど2つの異なる🌞
子クラスDragon型のオブジェクトPokkyの(親クラスから引き継いだ)メンバ関数
Pokky.statusDataDisplay()
の管理しているメモリ領域と
子クラスDragon型のオブジェクトPokkyの(子クラスに元から備わっている)メンバ関数
Pokky.statusDataDisplay()
の管理しているメモリ領域
が
🌞生成されていることになるんです🌞
そして
ptbの子クラスDragon*型のポインタ変数宣言
Dragon* ptb;
を実行して
子クラスDragon*型のポインタ変数
ptb
を作製します
子クラスDragon*型のポインタ変数ptbに
子クラスDragon型のオブジェクトPokkyのアドレス&Pokkyを
ptb=&Pokky;
と代入します
この場合
子クラスDragon*型のポインタ変数ptbにアロー演算子->を用いた
ptb->name
ptb->HP
ptb->MP
ptb->statusDataDisplay()
は
子クラスDragon型のオブジェクトPokkyの(親クラスから引き継いだ)メンバ変数
Pokky.name
Pokky.HP
Pokky.MP
子クラスDragon型のオブジェクトPokkyの(子クラスにもともと備わっている)メンバ関数
Pokky.statusDataDisplay()
と
同じ働きをすることになります」
マックス「
子クラスDragon型のオブジェクトPokkyの
Pokky.statusDataDisplay()
と同じ働きをする・・・か
オーバーライドがおこなわれているのか?」
ソーラー「そうなんです
子クラスDragon*型のポインタ変数ptbに
子クラスDragon型のオブジェクトPokkyのアドレス&Pokkyが代入された場合
オーバライドの働きにより
子クラスDragon*型のポインタ変数ptbにアロー演算子->を用いた
ptb->statusDataDisplay()
は
子クラスDragon型のオブジェクトPokkyの(親クラスから引き継いだ)メンバ関数
Pokky.statusDataDisplay()
が管理しているメモリ領域でなく
子クラスDragon型のオブジェクトPokkyの(子クラスにもともと備わっている)メンバ関数
Pokky.statusDataDisplay()
が管理しているメモリ領域
にアクセスすることになります
子クラスDragon*型のポインタ変数ptbに
子クラスDragon型のオブジェクトPokkyのアドレス&Pokkyを
代入したので
子クラスDragon*型のポインタ変数ptbにアロー演算子->を用いた
ptb->name
ptb->HP
ptb->MP
ptb->statusDataDisplay()
は
子クラスDragon型のオブジェクトPokkyの(親クラスから引き継いだ)メンバ変数
Pokky.name
Pokky.HP
Pokky.MP
が管理しているメモリ領域
と
子クラスDragon型のオブジェクトPokkyの(子クラスにもともと備わっている)メンバ関数
Pokky.statusDataDisplay()
が管理しているメモリ領域
にアクセスすることになったわけです
そして今回 新たに登場するパターンです
Pokkyの子クラスDragon型のオブジェクト宣言
Dragon Pokky;
の実行によって子クラスDragon型のオブジェクトPokkyが作製された場合
子クラスDragon型のオブジェクトPokkyの(親クラスから引き継いだ)メンバ変数
Pokky.name
Pokky.HP
Pokky.MP
子クラスDragon型のオブジェクトPokkyの(親クラスから引き継いだ)メンバ関数
Pokky.statusDataDisplay()
さらに
子クラスDragon型のオブジェクトPokkyの(子クラスに元から備わっている)メンバ変数
Pokky.DP
子クラスDragon型のオブジェクトPokkyの(子クラスに元から備わっている)メンバ関数
Pokky.statusDataDisplay()
が生成されることになります
🌞同じ名前の🌞
子クラスDragon型のオブジェクトPokkyの(親クラスから引き継いだ)メンバ関数
Pokky.statusDataDisplay()
と
子クラスDragon型のオブジェクトPokkyの(子クラスに元から備わっている)メンバ関数
Pokky.statusDataDisplay()
が
生成されているところが
🌞ポイントです🌞
このとき
子クラスDragon型のオブジェクトPokkyの(親クラスから引き継いだ)メンバ変数
Pokky.name
Pokky.HP
Pokky.MP
子クラスDragon型のオブジェクトPokkyの(親クラスから引き継いだ)メンバ関数
Pokky.statusDataDisplay()
が管理しているメモリ領域
と
子クラスDragon型のオブジェクトPokkyの(子クラスに元から備わっている)メンバ変数
Pokky.DP
子クラスDragon型のオブジェクトPokkyの(子クラスに元から備わっている)メンバ関数)
Pokky.statusDataDisplay()
が存在していることになります
🌞同じ名前だけど2つの異なる🌞
子クラスDragon型のオブジェクトPokkyの(親クラスから引き継いだ)メンバ関数
Pokky.statusDataDisplay()
の管理しているメモリ領域と
子クラスDragon型のオブジェクトPokkyの(子クラスに元から備わっている)メンバ関数
Pokky.statusDataDisplay()
の管理しているメモリ領域
が
🌞生成されていることになるんです🌞
このとき
ptaの子クラスDragon*型のポインタ変数宣言
Dragon* pta;
を実行して
子クラスDragon*型のポインタ変数
pta
を生成するのでなく
ptaの💖親クラスGameCharacter*型のポインタ変数宣言💖
GameCharacter* pta;
を実行して
親クラスGameCharacter*型のポインタ変数
pta
を作製します
そして
親クラスGameCharacter*型のポインタ変数ptaに
子クラスDragon型のオブジェクトPokkyのアドレス&Pokkyを
pta=&Pokky;
と代入します
この場合
親クラスGameCharacter*型のポインタ変数ptaにアロー演算子->を用いた
pta->name
pta->HP
pta->MP
pta->statusDataDisplay()
は
子クラスDragon型のオブジェクトPokkyの(親クラスから引き継いだ)メンバ変数
Pokky.name
Pokky.HP
Pokky.MP
子クラスDragon型のオブジェクトPokkyの(親クラスから引き継いだ)メンバ関数
Pokky.statusDataDisplay()
と
同じ働きをすることになります」
マックス「なんで なんかさっきとちがってないか?
pta->statusDataDisplay()
は
子クラスDragon型のオブジェクトPokkyの(親クラスに備わっている、親クラスから引き継いだ)メンバ関数
Pokky.statusDataDisplay()
と同じはたらきをすることになるのか?
オーバーライドはおこなわれないのか?」
ソーラー「それもそのはずなんです
Pokkyの子クラスDragon型のオブジェクト宣言
Dragon Pokky;
を実行し
🌞親クラスGameCharacter*型のポインタ変数ptaに🌞
子クラスDragon型のオブジェクトPokkyのアドレス&Pokkyを代入する
pta=&Pokky;
を実行した場合
親クラスGameCharacter*型のポインタ変数ptaにアロー演算子->を用いた
pta->name
pta->HP
pta->MP
pta->statusDataDisplay()
は
子クラスDragon型のオブジェクトPokkyの(親クラスから引き継いだ)メンバ変数
Pokky.name
Pokky.HP
Pokky.MP
子クラスDragon型のオブジェクトPokkyの(|親クラスに備わっている、親クラスから引き継いだ《🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞》)メンバ関数
Pokky.statusDataDisplay()
の管理しているメモリ領域にしかアクセスできないからなんです
親クラスGameCharacterのメンバ関数
statusDataDisplay()
と同じ名前のメンバ関数を
子クラスDragonのメンバ関数
statusDataDisplay()
として
設定する
オーバライドがしてあってもしてなくても
根本的に
💖親クラスGameCharacter*型のポインタ変数pta💖
にアロー演算子->を用いた
pta->statusDataDisplay()
では
子クラスDragon型のオブジェクトPokkyの(親クラスに備わっている、親クラスから引き継いだ)メンバ関数
Pokky.statusDataDisplay()
が管理しているメモリ領域にしかアクセスできません
子クラスDragon型のオブジェクトPokkyの(子クラスにもともと備わっている)メンバ関数
Pokky.statusDataDisplay()
が管理しているメモリ領域
にはアクセスできません
このように
💖親クラスGameCharacter*型のポインタ変数ptaに💖
🍋子クラスDragon型のオブジェクトPokkyのアドレス&Pokkyを🍋
代入した場合
親クラスGameCharacter*型のポインタ変数ptaにアロー演算子->を用いた
pta->name
pta->HP
pta->MP
pta->statusDataDisplay()
は
子クラスDragon型のオブジェクトPokkyの(親クラスに備わっている、親クラスから引き継いだ)メンバ変数
Pokky.name
Pokky.HP
Pokky.MP
が管理しているメモリ領域
と
子クラスDragon型のオブジェクトPokkyの(親クラスに備わっている、親クラスから引き継いだ)メンバ関数
Pokky.statusDataDisplay()
が管理しているメモリ領域
にしかアクセスできない
子クラスDragon型のオブジェクトPokkyの(子クラスに備わっている)メンバ変数
Pokky.DP
が管理しているメモリ領域
と
子クラスDragon型のオブジェクトPokkyの(子クラスに備わっている)メンバ関数
Pokky.statusDataDisplay()
が管理しているメモリ領域
にはアクセスできない
というのは
💖親クラスGameCharacter*型のポインタ変数ptaに💖
🍋子クラスDragon型のオブジェクトPokkyのアドレス&Pokkyを🍋
代入したことが
原因なんです
なぜなら
このエピソードの初めのほうでも述べられたように
親クラスGameCharacter型のオブジェクトPokkyのメンバ変数
Pokky.name
Pokky.HP
Pokky.MP
が管理しているメモリ領域と
親クラスGameCharacter型のオブジェクトPokkyのメンバ関数
Pokky.statusDataDisplay()
が管理しているメモリ領域
は
あるメモリ領域を占有していますが
それらのメモリをまとめて
ある変数が管理しているととらえると
それらのメモリを代表するアドレスもあるわけで
その変数のアドレスを格納する
その(変数の型)アスタリスク*型のポインタ変数も
登場してくることになります
同様に
子クラスDragon型のオブジェクトPokkyの(親クラスから引き継いだ)メンバ変数
Pokky.name
Pokky.HP
Pokky.MP
が管理しているメモリ領域と
子クラスDragon型のオブジェクトPokkyの(親クラスから引き継いだ)メンバ関数
Pokky.statusDataDisplay()
が管理しているメモリ領域
も
あるメモリ領域を占有していますが
それらのメモリをまとめて
ある変数が管理しているととらえると
それらのメモリを代表するアドレスもあるわけで
その変数のアドレスを格納する
その(変数の型)アスタリスク*型のポインタ変数も
登場してくることになるのですが
それらのメモリを代表するアドレスを格納しているのが
ともに
親クラスGameCharacter*型のポインタ変数ptaになっているというわけです
子クラスDragon型のオブジェクトPokkyは
🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞
子クラスDragon型のオブジェクトPokkyの(親クラスから引き継いだ)メンバ変数
Pokky.name
Pokky.HP
Pokky.MP
が管理しているメモリ領域と
子クラスDragon型のオブジェクトPokkyの(親クラスから引き継いだ)メンバ関数
Pokky.statusDataDisplay()
が管理しているメモリ領域
🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞
に加えて
💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖
子クラスDragon型のオブジェクトPokkyの(子クラスに元から備わっている)メンバ変数
Pokky.DP
が管理しているメモリ領域と
子クラスDragon型のオブジェクトPokkyの(子クラスに元から備わっている)メンバ関数
Pokky.statusDataDisplay()
が管理しているメモリ領域
💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖
を管理しているわけですが
🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞
子クラスDragon型のオブジェクトPokkyの(親クラスから引き継いだ)メンバ変数
Pokky.name
Pokky.HP
Pokky.MP
が管理しているメモリ領域と
子クラスDragon型のオブジェクトPokkyの(親クラスから引き継いだ)メンバ関数
Pokky.statusDataDisplay()
が管理しているメモリ領域
🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞
だけにアクセスできるのが
親クラスGameCharacter*型のポインタ変数ptaなんだね
子クラスDragon*型のポインタ変数ptaがアクセスできるのは
🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞
子クラスDragon型のオブジェクトPokkyの(親クラスから引き継いだ)メンバ変数
Pokky.name
Pokky.HP
Pokky.MP
が管理しているメモリ領域と
子クラスDragon型のオブジェクトPokkyの(親クラスから引き継いだ)メンバ関数
Pokky.statusDataDisplay()
が管理しているメモリ領域
🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞
に加えて
💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖
子クラスDragon型のオブジェクトPokkyの(子クラスに元から備わっている)メンバ変数
Pokky.DP
が管理しているメモリ領域と
子クラスDragon型のオブジェクトPokkyの(子クラスに元から備わっている)メンバ関数
Pokky.statusDataDisplay()
が管理しているメモリ領域
💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖
の両方というわけなんだよ
親クラスGameCharacter*型のポインタ変数ptaは
🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞
子クラスDragon型のオブジェクトPokkyの(親クラスから引き継いだ)メンバ変数
Pokky.name
Pokky.HP
Pokky.MP
が管理しているメモリ領域と
子クラスDragon型のオブジェクトPokkyの(親クラスから引き継いだ)メンバ関数
Pokky.statusDataDisplay()
が管理しているメモリ領域
🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞
だけなので
親クラスGameCharacter*型のポインタ変数ptaに
アロー演算子->が用いられた
Pokky->statusDataDisplay();
が実行されると
子クラスDragon型のオブジェクトPokkyの(親クラスから引き継いだ)メンバ関数
Pokky.statusDataDisplay();
に相当するものが実行されることになるんだよ
だから
Pokky->statusDataDisplay();
が実行されても
子クラスDragon型のオブジェクトPokkyの(オーバーライドしている子クラスに元から備わっている)メンバ関数
Pokky.statusDataDisplay();
に相当するものが実行されることはないんだ
オーバーライドが機能しないというわけだね
」
マックス「おうぅ
いい説明じゃないか
オーバーライドが機能しないか・・・
親クラスGameCharacter*型のポインタ変数ptaにアロー演算子->を用いた
pta->statusDataDisplay()
では
子クラスDragon型のオブジェクトPokkyの(子クラスに備わっている)メンバ関数
Pokky.statusDataDisplay()
が管理しているメモリ領域
にはアクセスできないか・・・
💖親クラスGameCharacter*型のポインタ変数ptaに💖
🍋子クラスDragon型のオブジェクトPokkyのアドレス&Pokkyを🍋
代入して
親クラスGameCharacter*型のポインタ変数ptaをつかうときの宿命というやつか・・・」
ソーラー「そうですね
ここまでで十分なかんじなんだけど
なんとかして
もっと簡単に
ちょっと別の感じの説明をおこなってみると
親クラスGameCharacter*型のポインタ変数
pta
に
🍋子クラスDragon型🍋のオブジェクトPokkyのアドレス
&Pokky
が代入された状態では
pta->name = "ポッキー";
pta->HP = 15;
pta->MP = 5;
🌞pta->statusDataDisplay();🌞
が実行されるとき
あたかも
ptaには
🍋子クラスDragon型🍋のオブジェクトPokkyのアドレス
&Pokky
が代入されているにもかかわらず
親クラスGam
親クラスGameCharact
が代入されているととらえれば
わかりやすいかな?」
マックス「
🍋子クラスDragon型🍋のオブジェクトPokkyのアドレス
&Pokky
が代入されているのではなく
親クラスGameCharacter*型のポインタ変数に
親クラスGameCharacter型のオブジェクトPokkyのアドレス
&Pokky
が代入されていることになるんかい
実際には
子クラスDragon型のオブジェクトPokkyのアドレス
&Pokky
が代入されているんだが
そう考えることもできるというわけだ
☆親クラスGameCharacter*型☆のポインタ変数ptaに
☆親クラスGameCharacter型☆のオブジェクトPokkyのアドレス&Pokky
か・・・
単純といえば単純か?」
ソーラー「そうなんです
親クラスGameCharacter型のオブジェクトPokkyを生成した場合の
親クラスGameCharacter型のオブジェクトPokkyのアドレス&Pokky
と
子クラスGameCharacter型のオブジェクトPokkyを生成した場合の
子クラスDragon型のオブジェクトPokkyのアドレス&Pokky
は
もちろん違うアドレス(異なるメモリのアドレス)ですが
親クラスGameCharacter*型のポインタ変数
pta
に
🍋子クラスDragon型🍋のオブジェクトPokkyのアドレス
&Pokky
が代入された状態を
💖親クラスGameCharacter型💖のオブジェクトPokkyのアドレス
&Pokky
が代入された状態ととらえると
わかりやすくなる
と思うんだ
ですので
親クラスGameCharacter*型のポインタ変数
pta
に
💖親クラスGameCharacter型💖のオブジェクトPokkyのアドレス
&Pokky
が代入された状態ととらえると
Pokky->name
Pokky->HP
Pokky->MP
は
オブジェクトPokkyのメンバ変数
Pokky.name
Pokky.HP
Pokky.MP
に相当していると
とらえることができます
もちろん
pta->statusDataDisplay()
は
💖親クラスGameCharacter型💖の
オブジェクトPokkyのメンバ関数
Pokky.statusDataDisplay()
に相当するものととらえることができます
pta->statusDataDisplay()
は
💖親クラスGameCharacter型💖の
オブジェクトPokkyのメンバ関数
Pokky.statusDataDisplay()
ととらえると
pta->statusDataDisplay()
が実行されると何が実行されるか
がわかりやすくなります
その場合
pta->statusDataDisplay();
が実行されたなら
親クラスGameCharacterのメンバ関数の定義
👇
void GameCharacter::statusDataDisplay() {
cout << name << "\n";
cout << "HP " << HP << "\n";
cout << "MP " << MP << "\n";
cout << "親クラスのメンバ関数statusDataDisplay()が実行されました" << "\n";
}
の
name
HP
MP
に
Pokky.name
Pokky.HP
Pokky.MP
が代入されたものが実行されることになるので
コマンドプロンプト画面に
ポッキー
HP 15
MP 5
親クラスのメンバ関数statusDataDisplay()が実行されました
が表示されることがわかりますね
つまり
親クラスGameCharacter*型のポインタ変数
pta
に
Pokkyの子クラスDragon型のオブジェクト宣言
Dragon Pokky;
により生成される
子クラスDragon型のオブジェクトPokkyのアドレス
&Pokky
が代入されるということを
単純に
Pokkyの親クラスGameCharacter型のオブジェクト宣言
GameCharacter Pokky;
が実行されて
生成される
親クラスGameCharacter型のオブジェクトPokkyのアドレス
&Pokky
が
親クラスGameCharacter*型のポインタ変数
pta
に
代入されると
とらえたというわけです
正しくはないんだけど
このように理解しても
そんなに問題はないんだ😊」
マックス「おお うまい方法をおもいついたな」
新規登録で充実の読書を
- マイページ
- 読書の状況から作品を自動で分類して簡単に管理できる
- 小説の未読話数がひと目でわかり前回の続きから読める
- フォローしたユーザーの活動を追える
- 通知
- 小説の更新や作者の新作の情報を受け取れる
- 閲覧履歴
- 以前読んだ小説が一覧で見つけやすい
アカウントをお持ちの方はログイン
ビューワー設定
文字サイズ
背景色
フォント
組み方向
機能をオンにすると、画面の下部をタップする度に自動的にスクロールして読み進められます。
応援すると応援コメントも書けます