ですので  親クラスアスタリスク*型のポインタ変数に子クラス型のオブジェクトのアドレスを代入をしたり親クラス&型の参照変数に子クラス型のオブジェクトを代入することができます

親クラスアスタリスク*型のポインタ変数に子クラス型のオブジェクトのアドレスを代入するということは単純に親クラス型のオブジェクトのアドレスを代入していると捉えることができます

ソーラー「

     

前のエピソードで見てきたように


親クラスアスタリスク*型のポインタ変数には

親クラス型のオブジェクトのアドレス

あるいは

子クラス型のオブジェクトのアドレス



子クラスアスタリスク*型のポインタ変数には

子クラス型のオブジェクトのアドレスのみを


代入することができました



では

親クラスアスタリスク*型のポインタ変数に



     🌞子クラス型のオブジェクトのアドレスが代入されたとき🌞



プログラムをご覧ください

👇

#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


が代入されているにもかかわらず


親クラスGameCharacter型のオブジェクト宣言💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖


GameCharacter Pokky;💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖


により生成される💖💖💖💖💖💖💖💖💖


親クラスGameCharacter型のオブジェクトPokkyのアドレス💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖


&Pokky💖💖💖💖💖💖💖💖💖


が代入されているととらえれば


わかりやすいかな?」


マックス「


🍋子クラス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


代入されると


とらえたというわけです


正しくはないんだけど


このように理解しても


そんなに問題はないんだ😊」



マックス「おお うまい方法をおもいついたな」

  • Twitterで共有
  • Facebookで共有
  • はてなブックマークでブックマーク

作者を応援しよう!

ハートをクリックで、簡単に応援の気持ちを伝えられます。(ログインが必要です)

応援したユーザー

応援すると応援コメントも書けます

新規登録で充実の読書を

マイページ
読書の状況から作品を自動で分類して簡単に管理できる
小説の未読話数がひと目でわかり前回の続きから読める
フォローしたユーザーの活動を追える
通知
小説の更新や作者の新作の情報を受け取れる
閲覧履歴
以前読んだ小説が一覧で見つけやすい
新規ユーザー登録無料

アカウントをお持ちの方はログイン

カクヨムで可能な読書体験をくわしく知る