仮想関数システムが機能するには親クラス&型の参照変数に子クラス型のオブジェクトが代入されるか親クラス*型のポインタ変数に子クラス型のオブジェクトのアドレスが代入される必要があります

親クラスのメンバ関数にvirtualをつけて仮想関数にするだけで親クラス&型の参照変数に子クラス型のオブジェクトを代入したとき簡単にオーバーライドした子クラスのメンバ関数を実行できるようになります

ソーラー「ここで登場するのが



         😊仮想関数😊


なんです


仮想関数を用いる前の


先程のプログラムはこちらでした

👇」


#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";


}



class Human :public GameCharacter {

public:

int TP;//👈Human(人間)型のキャラクターだけに備わっているテクニックポイントです

void statusDataDisplay();//🌞メンバ関数statusDataDisplay()のオーバーライドを行っています


void scanGameCharacterData(GameCharacter& a);


};


//👇🌞🌞🌞クラスHumanのメンバ関数statusDataDisplay() の定義です🌞🌞🌞

void Human::statusDataDisplay() {


cout << name << "\n";

cout << "HP " << HP << "\n";

cout << "MP " << MP << "\n";

cout << "TP " << TP << "\n";

}




//👇🌞🌞🌞クラスHumanのメンバ関数scanGameCharacterData(GameCharacter& a)の定義です🌞🌞🌞



void Human::scanGameCharacterData(GameCharacter& a) {

cout << "スキャン発動!" << "\n";

cout << name << "は" << a.name << "のスキャンを開始した" << "\n";

cout << "ステータスデータ" << "\n";


a.statusDataDisplay();


}


class Dragon :public GameCharacter {

public:


int DP;//👈ドラゴン型のキャラクターだけに備わっているドラゴンポイントです

void statusDataDisplay();


};



//👇🌞🌞🌞クラスDragonのメンバ関数statusDataDisplay() の定義です🌞🌞🌞

void Dragon::statusDataDisplay() {


cout << name << "\n";

cout << "HP " << HP << "\n";

cout << "MP " << MP << "\n";

cout << "DP " << DP << "\n";

}



class Elf :public GameCharacter {

public:


int EP;//👈エルフ型のキャラクターだけに備わっているエルフポイントです

void statusDataDisplay();

//親クラスGameCharacterのメンバ関数statusDataDisplay()をオーバーライドしています

};



//👇🌞🌞🌞クラスElfのメンバ関数statusDataDisplay() の定義です🌞🌞🌞

void Elf::statusDataDisplay() {


cout << name << "\n";

cout << "HP " << HP << "\n";

cout << "MP " << MP << "\n";

cout << "EP " << EP << "\n";

}



int main() {


Human Lyliane;

Lyliane.name = "リリアーネ";

Lyliane.HP = 10;

Lyliane.MP = 5;

Lyliane.TP = 7;


Dragon Pokky;

Pokky.name = "ポッキー";

Pokky.HP = 20;

Pokky.MP = 3;

Pokky.DP = 2;


Elf Sylphy;

Sylphy.name = "シルフィ";

Sylphy.HP = 3;

Sylphy.MP = 18;

Sylphy.EP = 3;


Lyliane.scanGameCharacterData(Pokky);

Lyliane.scanGameCharacterData(Sylphy);

Lyliane.scanGameCharacterData(Lyliane);


return 0;

}


プログラムの実行結果


スキャン発動!

リリアーネはポッキーのスキャンを開始した

ステータスデータ

ポッキー

HP 20

MP 3

スキャン発動!

リリアーネはシルフィのスキャンを開始した

ステータスデータ

シルフィ

HP 3

MP 18

スキャン発動!

リリアーネはリリアーネのスキャンを開始した

ステータスデータ

リリアーネ

HP 10

MP 5



ソーラー「このプログラムの



Lyliane.scanGameCharacterData(Pokky);


が実行されると



子クラスHumanのメンバ関数scanGameCharacterData(GameCharacter& a)の定義

👇

void Human::scanGameCharacterData(GameCharacter& a) {

cout << "スキャン発動!" << "\n";

cout << name << "は" << a.name << "のスキャンを開始した" << "\n";

cout << "ステータスデータ" << "\n";


a.statusDataDisplay();


}

👆


GameCharacter& aに


      子クラスDragon型のオブジェクトPokky


が代入されることになりますね



      親クラスGameCharacter&型の参照変数a


では


子クラスDragon型のオブジェクトPokkyの(親クラスから引き継いだ)メンバ変数

Pokky.name

Pokky.HP

Pokky.MP


子クラスDragon型のオブジェクトPokkyの(親クラスから引き継いだ)メンバ関数

Pokky.statusDataDisplay()


の管理しているメモリ領域にしかアクセスできません


すると


子クラスHumanのメンバ関数scanGameCharacterData(GameCharacter& a)の定義

👇

void Human::scanGameCharacterData(GameCharacter& a) {

cout << "スキャン発動!" << "\n";

cout << name << "は" << a.name << "のスキャンを開始した" << "\n";

cout << "ステータスデータ" << "\n";


a.statusDataDisplay();


}

👆


nameはLyliane.name


a.nameはPokky.name


a.statusDataDisplay()は


Pokky.statusDataDisplay()


を表すことになります



ですので


Lyliane.scanGameCharacterData(Pokky);


が実行されると


cout << "スキャン発動!" << "\n";

cout << Lyliane.name << "は" << Pokky.name << "のスキャンを開始した" << "\n";

cout << "ステータスデータ" << "\n";


Pokky.statusDataDisplay();


が実行されることになります


Pokky.statusDataDisplay();


が実行されるとき


親クラスGameCharacterのメンバ関数


statusDataDisplay()


の定義が用いられることになります


親クラスGameCharacterのメンバ関数


statusDataDisplay()


の定義は


void GameCharacter::statusDataDisplay() {


cout << name << "\n";

cout << "HP " << HP << "\n";

cout << "MP " << MP << "\n";


}


なので


cout << "スキャン発動!" << "\n";

cout << Lyliane.name << "は" << Pokky.name << "のスキャンを開始した" << "\n";

cout << "ステータスデータ" << "\n";


Pokky.statusDataDisplay();


が実行されると



リリアーネはポッキーのスキャンを開始した

ステータスデータ

ポッキー

HP 20

MP 3


がコマンドプロンプト画面表示されることになります





           てへへ



さあ


ここからが楽しいんだ😊


次の改良したプログラムをごらんください


改良したプログラムは


親クラスGameCharacterのメンバ関数statusDataDisplay()に


virtual


を付けただけです


👇


#include <iostream>

#include <string>//文字列を取り扱うためにヘッダファイル <string>をインクルードしています

using namespace std;


class GameCharacter {


public:

string name;

int HP;

int MP;


virtual void statusDataDisplay();//👈ここです🌞🌞🌞えここにvirtualをつけただけです



};



void GameCharacter::statusDataDisplay() {


cout << name << "\n";

cout << "HP " << HP << "\n";

cout << "MP " << MP << "\n";


}



class Human :public GameCharacter {

public:

int TP;//👈Human(人間)型のキャラクターだけに備わっているテクニックポイントです

void statusDataDisplay();//🌞メンバ関数statusDataDisplay()のオーバーライドを行っています


void scanGameCharacterData(GameCharacter& a);


};


//👇🌞🌞🌞クラスHumanのメンバ関数statusDataDisplay() の定義です🌞🌞🌞

void Human::statusDataDisplay() {


cout << name << "\n";

cout << "HP " << HP << "\n";

cout << "MP " << MP << "\n";

cout << "TP " << TP << "\n";

}




//👇🌞🌞🌞クラスHumanのメンバ関数scanGameCharacterData(GameCharacter& a)の定義です🌞🌞🌞



void Human::scanGameCharacterData(GameCharacter& a) {

cout << "スキャン発動!" << "\n";

cout << name << "は" << a.name << "のスキャンを開始した" << "\n";

cout << "ステータスデータ" << "\n";


a.statusDataDisplay();


}


class Dragon :public GameCharacter {

public:


int DP;//👈ドラゴン型のキャラクターだけに備わっているドラゴンポイントです

void statusDataDisplay();


};



//👇🌞🌞🌞クラスDragonのメンバ関数statusDataDisplay() の定義です🌞🌞🌞

void Dragon::statusDataDisplay() {


cout << name << "\n";

cout << "HP " << HP << "\n";

cout << "MP " << MP << "\n";

cout << "DP " << DP << "\n";

}



class Elf :public GameCharacter {

public:


int EP;//👈エルフ型のキャラクターだけに備わっているエルフポイントです

void statusDataDisplay();

//親クラスGameCharacterのメンバ関数statusDataDisplay()をオーバーライドしています

};



//👇🌞🌞🌞クラスElfのメンバ関数statusDataDisplay() の定義です🌞🌞🌞

void Elf::statusDataDisplay() {


cout << name << "\n";

cout << "HP " << HP << "\n";

cout << "MP " << MP << "\n";

cout << "EP " << EP << "\n";

}



int main() {


Human Lyliane;

Lyliane.name = "リリアーネ";

Lyliane.HP = 10;

Lyliane.MP = 5;

Lyliane.TP = 7;


Dragon Pokky;

Pokky.name = "ポッキー";

Pokky.HP = 20;

Pokky.MP = 3;

Pokky.DP = 2;


Elf Sylphy;

Sylphy.name = "シルフィ";

Sylphy.HP = 3;

Sylphy.MP = 18;

Sylphy.EP = 3;


Lyliane.scanGameCharacterData(Pokky);

Lyliane.scanGameCharacterData(Sylphy);

Lyliane.scanGameCharacterData(Lyliane);


return 0;

}


プログラムの実行結果


スキャン発動!

リリアーネはポッキーのスキャンを開始した

ステータスデータ

ポッキー

HP 20

MP 3

DP 2

スキャン発動!

リリアーネはシルフィのスキャンを開始した

ステータスデータ

シルフィ

HP 3

MP 18

EP 3

スキャン発動!

リリアーネはリリアーネのスキャンを開始した

ステータスデータ

リリアーネ

HP 10

MP 5

TP 7


マックス「超簡単に


プログラムの実行結果


スキャン発動!

リリアーネはポッキーのスキャンを開始した

ステータスデータ

ポッキー

HP 20

MP 3

スキャン発動!

リリアーネはシルフィのスキャンを開始した

ステータスデータ

シルフィ

HP 3

MP 18

スキャン発動!

リリアーネはリリアーネのスキャンを開始した

ステータスデータ

リリアーネ

HP 10

MP 5



プログラムの実行結果


スキャン発動!

リリアーネはポッキーのスキャンを開始した

ステータスデータ

ポッキー

HP 20

MP 3

DP 2

スキャン発動!

リリアーネはシルフィのスキャンを開始した

ステータスデータ

シルフィ

HP 3

MP 18

EP 3

スキャン発動!

リリアーネはリリアーネのスキャンを開始した

ステータスデータ

リリアーネ

HP 10

MP 5

TP 7


に変更できた!



っこれはすごいじゃないか!!!」


ソーラー「


Lyliane.scanGameCharacterData(Pokky);


が実行されると



子クラスHumanのメンバ関数scanGameCharacterData(GameCharacter& a)の定義

👇

void Human::scanGameCharacterData(GameCharacter& a) {

cout << "スキャン発動!" << "\n";

cout << name << "は" << a.name << "のスキャンを開始した" << "\n";

cout << "ステータスデータ" << "\n";


a.statusDataDisplay();


}

👆


GameCharacter& aに


      子クラスDragon型のオブジェクトPokky


が代入されることになります



Lyliane.scanGameCharacterData(Pokky);


が実行されると


子クラスHumanのメンバ関数scanGameCharacterData(GameCharacter& a)の定義

👇

void Human::scanGameCharacterData(GameCharacter& a) {

cout << "スキャン発動!" << "\n";

cout << name << "は" << a.name << "のスキャンを開始した" << "\n";

cout << "ステータスデータ" << "\n";


a.statusDataDisplay();


}

👆


nameはLyliane.name


a.nameはPokky.name


a.statusDataDisplay()は


Pokky.statusDataDisplay()


を表すことになります


ですので


Lyliane.scanGameCharacterData(Pokky);


が実行されると


cout << "スキャン発動!" << "\n";

cout << Lyliane.name << "は" << Pokky.name << "のスキャンを開始した" << "\n";

cout << "ステータスデータ" << "\n";


Pokky.statusDataDisplay();


が実行されることになります


このとき


Pokky.statusDataDisplay();


が実行されると


仮想関数である


親クラスGameCharacterのメンバ関数


statusDataDisplay()


でなく


親クラスGameCharacterのメンバ関数


statusDataDisplay()


をオーバーライドしている同じ名前の


子クラスDragonのメンバ関数


statusDataDisplay()


の定義が用いられることになります


子クラスDragonのメンバ関数


statusDataDisplay()


の定義は


void Dragon::statusDataDisplay() {


cout << name << "\n";

cout << "HP " << HP << "\n";

cout << "MP " << MP << "\n";

cout << "DP " << DP << "\n";

}


なので


cout << "スキャン発動!" << "\n";

cout << Lyliane.name << "は" << Pokky.name << "のスキャンを開始した" << "\n";

cout << "ステータスデータ" << "\n";


Pokky.statusDataDisplay();


が実行されると


プログラムの実行結果


リリアーネはポッキーのスキャンを開始した

ステータスデータ

ポッキー

HP 20

MP 3

DP 2

コマンドプロンプト画面表示されることになります



           通常



      親クラスGameCharacter&型の参照変数a


では

👇

子クラスDragon型のオブジェクトPokkyの(親クラスから引き継いだ)メンバ変数

Pokky.name

Pokky.HP

Pokky.MP


子クラスDragon型のオブジェクトPokkyの(親クラスから引き継いだ)メンバ関数

Pokky.statusDataDisplay()

👆

の管理しているメモリ領域にしかアクセスできないのですが



👇

子クラスDragon型のオブジェクトPokkyの(親クラスから引き継いだ)メンバ変数

Pokky.name

Pokky.HP

Pokky.MP


子クラスDragon型のオブジェクトPokkyの(statusDataDisplay())メンバ関数

Pokky.statusDataDisplay()

👆

の管理しているメモリ領域


にアクセスできることになります



簡単だったかな?


ポイントは



Lyliane.scanGameCharacterData(Pokky);


が実行されると



子クラスHumanのメンバ関数scanGameCharacterData(GameCharacter& a)の定義

👇

void Human::scanGameCharacterData(GameCharacter& a) {

cout << "スキャン発動!" << "\n";

cout << name << "は" << a.name << "のスキャンを開始した" << "\n";

cout << "ステータスデータ" << "\n";


a.statusDataDisplay();


}

👆


GameCharacter& aに


      子クラスDragon型のオブジェクトPokky


が代入されます


このように


GameCharacter& aに


      子クラスDragon型のオブジェクトPokky


が代入された時に限り


a.statusDataDisplay()


の実行において


仮想関数である親クラスGameCharacterのメンバ関数


statusDataDisplay()

の定義は用いられず


オーバーライドしている


子クラスGameCharacterのメンバ関数


statusDataDisplay()


の定義が用いられることになります





ここで注意点があります



オーバーライドが起きるのは


GameCharacter& aに


      子クラスDragon型のオブジェクトPokky


が代入された時に限ります


GameCharacter aに


      子クラスDragon型のオブジェクトPokky


が代入された時にはオーバーライドはおこりません



子クラスHumanのメンバ関数scanGameCharacterData(GameCharacter& a)の定義

👇

void Human::scanGameCharacterData(GameCharacter& a) {

cout << "スキャン発動!" << "\n";

cout << name << "は" << a.name << "のスキャンを開始した" << "\n";

cout << "ステータスデータ" << "\n";


a.statusDataDisplay();


}

👆


GameCharacter& aが


GameCharacter aに設定されているとします


👇

void Human::scanGameCharacterData(GameCharacter a) {

cout << "スキャン発動!" << "\n";

cout << name << "は" << a.name << "のスキャンを開始した" << "\n";

cout << "ステータスデータ" << "\n";


a.statusDataDisplay();


}

👆


このように設定されていると


Lyliane.scanGameCharacterData(Pokky);


が実行されたとき


このときも


GameCharacter aに



      子クラスDragon型のオブジェクトPokky



が代入されることになります


このとき



親クラスGameCharacter型のオブジェクトaに


子クラスDragon型のオブジェクトPokkyのメンバ変数


Pokky.name

Pokky.HP

Pokky.MP

に格納されている

ポッキー

20

3

だけが


           💖値渡し💖されることになります



つまり


void Human::scanGameCharacterData(GameCharacter a) {

cout << "スキャン発動!" << "\n";

cout << name << "は" << a.name << "のスキャンを開始した" << "\n";

cout << "ステータスデータ" << "\n";


a.statusDataDisplay();


}


の実行において


nameにはLyliane.nameが代入され


a.nameにはPokky.nameの格納している


文字データ "ポッキー"


が代入されます


そして


a.statusDataDisplay()は


のaには


子クラスDragon型のオブジェクトPokkyが代入されているような状態になるのですが


クラスGameCharacter型のaが用いられた


a.statusDataDisplay()


が実行されることに変わりはありません


この場合


a.statusDataDisplay()


の実行においては


親クラスGameCharacterのメンバ関数statusDataDisplay()


の定義が用いられることになります


オーバーライドしている


子クラスDragonのメンバ関数statusDataDisplay()


の定義が用いられることはありません


なぜなら


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


GameCharacter aに


よって生成される


親クラスGameCharacterのオブジェクトa💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖


子クラスDragon型のオブジェクトPokkyを代入しているのが原因です


  🌞aは親クラスGameCharacterのオブジェクトなので🌞


親クラスGameCharacterのオブジェクトaでは


親クラスGameCharacterのメンバ関数statusDataDisplay()が用いられた


a.statusDataDisplay()


しか実行することができません



ですので


cout << "スキャン発動!" << "\n";

cout << name << "は" << a.name << "のスキャンを開始した" << "\n";

cout << "ステータスデータ" << "\n";


a.statusDataDisplay();


が実行されると


イコール


cout << "スキャン発動!" << "\n";

cout << Lyliane.name << "は" << Pokky.name << "のスキャンを開始した" << "\n";

cout << "ステータスデータ" << "\n";


Pokky.statusDataDisplay();


が実行されることになり


プログラムの実行結果に


スキャン発動!

リリアーネはポッキーのスキャンを開始した

ステータスデータ

ポッキー

HP 20

MP 3

//🌞DP 7は表示されません🌞


が表示されることになります


つまり


仮想関数である親クラスGameCharacterのメンバ関数


statusDataDisplay()

の定義が用いられ


オーバーライドしている


子クラスGameCharacterのメンバ関数


statusDataDisplay()


の定義が用いられるようなことはおこりません


そのことを示すプログラムはこちらです

👇

#include <iostream>

#include <string>//文字列を取り扱うためにヘッダファイル <string>をインクルードしています

using namespace std;


class GameCharacter {


public:

string name;

int HP;

int MP;


virtual void statusDataDisplay();



};



void GameCharacter::statusDataDisplay() {


cout << name << "\n";

cout << "HP " << HP << "\n";

cout << "MP " << MP << "\n";


}



class Human :public GameCharacter {

public:

int TP;//👈Human(人間)型のキャラクターだけに備わっているテクニックポイントです

void statusDataDisplay();//🌞メンバ関数statusDataDisplay()のオーバーライドを行っています


void scanGameCharacterData(GameCharacter a);


};


//👇🌞🌞🌞クラスHumanのメンバ関数statusDataDisplay() の定義です🌞🌞🌞

void Human::statusDataDisplay() {


cout << name << "\n";

cout << "HP " << HP << "\n";

cout << "MP " << MP << "\n";

cout << "TP " << TP << "\n";

}




//👇🌞🌞🌞クラスHumanのメンバ関数scanGameCharacterData(GameCharacter& a)の定義です🌞🌞🌞



void Human::scanGameCharacterData(GameCharacter a) {

cout << "スキャン発動!" << "\n";

cout << name << "は" << a.name << "のスキャンを開始した" << "\n";

cout << "ステータスデータ" << "\n";


a.statusDataDisplay();


}


class Dragon :public GameCharacter {

public:


int DP;//👈ドラゴン型のキャラクターだけに備わっているドラゴンポイントです

void statusDataDisplay();


};



//👇🌞🌞🌞クラスDragonのメンバ関数statusDataDisplay() の定義です🌞🌞🌞

void Dragon::statusDataDisplay() {


cout << name << "\n";

cout << "HP " << HP << "\n";

cout << "MP " << MP << "\n";

cout << "DP " << DP << "\n";

}



class Elf :public GameCharacter {

public:


int EP;//👈エルフ型のキャラクターだけに備わっているエルフポイントです

void statusDataDisplay();

//親クラスGameCharacterのメンバ関数statusDataDisplay()をオーバーライドしています

};



//👇🌞🌞🌞クラスElfのメンバ関数statusDataDisplay() の定義です🌞🌞🌞

void Elf::statusDataDisplay() {


cout << name << "\n";

cout << "HP " << HP << "\n";

cout << "MP " << MP << "\n";

cout << "EP " << EP << "\n";

}



int main() {


Human Lyliane;

Lyliane.name = "リリアーネ";

Lyliane.HP = 10;

Lyliane.MP = 5;

Lyliane.TP = 7;


Dragon Pokky;

Pokky.name = "ポッキー";

Pokky.HP = 20;

Pokky.MP = 3;

Pokky.DP = 2;


Elf Sylphy;

Sylphy.name = "シルフィ";

Sylphy.HP = 3;

Sylphy.MP = 18;

Sylphy.EP = 3;


Lyliane.scanGameCharacterData(Pokky);

Lyliane.scanGameCharacterData(Sylphy);

Lyliane.scanGameCharacterData(Lyliane);


return 0;

}


プログラムの実行結果


スキャン発動!

リリアーネはポッキーのスキャンを開始した

ステータスデータ

ポッキー

HP 20

MP 3

スキャン発動!

リリアーネはシルフィのスキャンを開始した

ステータスデータ

シルフィ

HP 3

MP 18

スキャン発動!

リリアーネはリリアーネのスキャンを開始した

ステータスデータ

リリアーネ

HP 10

MP 5



ソーラー「


Lyliane.scanGameCharacterData(Pokky);

Lyliane.scanGameCharacterData(Sylphy);

Lyliane.scanGameCharacterData(Lyliane);


のいずれの実行の場合でも


親クラスGameCharacterのメンバ関数を


オーバーライドしている


子クラスGameCharacterのメンバ関数


statusDataDisplay()


の定義はもちいられず


仮想関数である親クラスGameCharacterのメンバ関数


statusDataDisplay()


の定義がもちいられています




       🌞オーバーライドが起きるのは🌞



    🌞親クラスGameCharacter&の参照変数aに🌞


🌞子クラスDragonのオブジェクトPokkyそのもの(実体)が代入されるときだけ🌞


なんです


もしくは


    🌞親クラスGameCharacter*のポインタ変数ptaに🌞


🌞子クラスDragonのオブジェクトのアドレス&Pokkyが代入(参照渡し)されるときだけ🌞なんです




このことはつまり


親クラスGameCharacter型のオブジェクトaに



    子クラスDragon型のオブジェクトのデータを値渡し


するだけでは


親クラスGameCharacter型のオブジェクトaは


そのまんま(笑)


親クラスGameCharacter型のオブジェクトaをあらわすことになり


a.statusDataDisplay()


の実行においては


親クラスGameCharacterのメンバ関数statusDataDisplay()の定義が用いられることになります


オーバーライドしている


子クラスDragonの


メンバ関数statusDataDisplay()の定義が用いられることはありません」








ちょっと先走っているおまけです


後に詳しく解説されることになります

👇




 親クラスGameCharacter*のポインタ変数ptaに


子クラスDragonのオブジェクトのアドレス&Pokkyが代入(参照渡し)されるときのプログラムはこちらです


👇

      

#include <iostream>

#include <string>//文字列を取り扱うためにヘッダファイル <string>をインクルードしています

using namespace std;


class GameCharacter {


public:

string name;

int HP;

int MP;


virtual void statusDataDisplay();



};



void GameCharacter::statusDataDisplay() {


cout << name << "\n";

cout << "HP " << HP << "\n";

cout << "MP " << MP << "\n";


}



class Human :public GameCharacter {

public:

int TP;//👈Human(人間)型のキャラクターだけに備わっているテクニックポイントです

void statusDataDisplay();//🌞メンバ関数statusDataDisplay()のオーバーライドを行っています


void scanGameCharacterData(GameCharacter* pta);


};


//👇🌞🌞🌞クラスHumanのメンバ関数statusDataDisplay() の定義です🌞🌞🌞

void Human::statusDataDisplay() {


cout << name << "\n";

cout << "HP " << HP << "\n";

cout << "MP " << MP << "\n";

cout << "TP " << TP << "\n";

}




//👇🌞🌞🌞クラスHumanのメンバ関数scanGameCharacterData(GameCharacter& a)の定義です🌞🌞🌞



void Human::scanGameCharacterData(GameCharacter* pta) {

cout << "スキャン発動!" << "\n";

cout << name << "は" << pta->name << "のスキャンを開始した" << "\n";

cout << "ステータスデータ" << "\n";


pta->statusDataDisplay();


}


class Dragon :public GameCharacter {

public:


int DP;//👈ドラゴン型のキャラクターだけに備わっているドラゴンポイントです

void statusDataDisplay();


};



//👇🌞🌞🌞クラスDragonのメンバ関数statusDataDisplay() の定義です🌞🌞🌞

void Dragon::statusDataDisplay() {


cout << name << "\n";

cout << "HP " << HP << "\n";

cout << "MP " << MP << "\n";

cout << "DP " << DP << "\n";

}



class Elf :public GameCharacter {

public:


int EP;//👈エルフ型のキャラクターだけに備わっているエルフポイントです

void statusDataDisplay();

//親クラスGameCharacterのメンバ関数statusDataDisplay()をオーバーライドしています

};



//👇🌞🌞🌞クラスElfのメンバ関数statusDataDisplay() の定義です🌞🌞🌞

void Elf::statusDataDisplay() {


cout << name << "\n";

cout << "HP " << HP << "\n";

cout << "MP " << MP << "\n";

cout << "EP " << EP << "\n";

}



int main() {


Human Lyliane;

Lyliane.name = "リリアーネ";

Lyliane.HP = 10;

Lyliane.MP = 5;

Lyliane.TP = 7;


Dragon Pokky;

Pokky.name = "ポッキー";

Pokky.HP = 20;

Pokky.MP = 3;

Pokky.DP = 2;


Elf Sylphy;

Sylphy.name = "シルフィ";

Sylphy.HP = 3;

Sylphy.MP = 18;

Sylphy.EP = 3;


Lyliane.scanGameCharacterData(&Pokky);

Lyliane.scanGameCharacterData(&Sylphy);

Lyliane.scanGameCharacterData(&Lyliane);


return 0;

}


プログラムの実行結果


スキャン発動!

リリアーネはポッキーのスキャンを開始した

ステータスデータ

ポッキー

HP 20

MP 3

DP 2

スキャン発動!

リリアーネはシルフィのスキャンを開始した

ステータスデータ

シルフィ

HP 3

MP 18

EP 3

スキャン発動!

リリアーネはリリアーネのスキャンを開始した

ステータスデータ

リリアーネ

HP 10

MP 5

TP 7



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

作者を応援しよう!

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

応援したユーザー

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

新規登録で充実の読書を

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

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

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