ポリモーフィズム(多態性)が用いられたプログラムを実行してみましょう その1




ソーラー「今日はポリモーフィズム


が用いられたプログラムを観察してみたいと思います



           ポリモーフィズム(多態性)


とは何のことかな


その説明の


準備としてはですね


そうだなあ


今まで登場した


親クラスGameCharacter



子クラスDragon


子クラスHuman


子クラスElf


に登場してもらおっか(#^^#)


親クラスGameCharacterのメンバ関数宣言


void statusDataDisplay();


virtual void statusDataDisplay();



virtual void statusDataDisplay()=0; 


のように


virtual

もしくは

virtual

=0;


をくっつけて


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



仮想関数


もしくは


純粋仮想関数に


設定します


その状態で


子クラス側で


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



               と


🌞"同じ名前"の子クラスDragonのメンバ関数statusDataDisplay()を設定する🌞


      

              すなわち



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


               を


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



           オーバーライドしておきます



そして


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


Dragon Pokky;


を実行して


子クラスDragon型のオブジェクトPokkyを作製したとします


次に


aの親クラスGameCharacter*型のポインタ変数宣言,初期化


GameCharacter* a=&Pokky;


を実行することにより


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


子クラスDragon型のオブジェクトPokkyのアドレス&Pokkyを代入して


a->statusDataDisplay();


を実行した場合は


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



仮想関数もしくは純粋仮想関数で


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


によってオーバーライドされているので


親クラスGameCharacterのメンバ関数statusDataDisplay()の定義は用いられず


子クラスDragonのメンバ関数statusDataDisplay()の定義が用いられた



子クラスDragon型のオブジェクトPokkyの(オーバーライドしている)メンバ関数


Pokky.statusDataDisplay();


に相当するものが実行されることになります



さらに


子クラスHumanに


メンバ関数statusDataDisplay()が設定されているとします


そして


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


違う子クラスHuman型のオブジェクトLylianeのアドレス&Lyliane


を代入して


a->statusDataDisplay()


を実行すると


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



仮想関数もしくは純粋仮想関数で


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


によってオーバーライドされているので



親クラスGameCharacterのメンバ関数statusDataDisplay()の定義は用いられず


子クラスHumanのメンバ関数statusDataDisplay()の定義が用いられた



子クラスHuman型のオブジェクトLylianeの(オーバーライドしている)メンバ関数


Lyliane.statusDataDisplay();


に相当するものが実行されることになります


もちろん


       a->statusDataDisplay()


の形式はそのままでOKというわけです




さらに


子クラスElfに


メンバ関数statusDataDisplay()が設定されているとします


そして


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


違う子クラスElf型のオブジェクトSylphineのアドレス&Sylphine



を代入して


a->statusDataDisplay()


を実行すると


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



仮想関数もしくは純粋仮想関数で


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


によってオーバーライドされているので



親クラスGameCharacterのメンバ関数statusDataDisplay()の定義は用いられず


子クラスElfのメンバ関数statusDataDisplay()の定義が用いられた



子クラスElf型のオブジェクトSylphineの(オーバーライドしている)メンバ関数


Sylphine.statusDataDisplay();


に相当するものが実行されることになります


もちろん


       a->statusDataDisplay()


の形式はそのままでOKというわけです





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

👇

#include <iostream>

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

using namespace std;



class GameCharacter {


public:

string name;

int HP;

int MP;

virtual void statusDataDisplay() = 0;

};



class Human :public GameCharacter {

public:

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

void statusDataDisplay();


};



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

void Human::statusDataDisplay() {


cout << name << "\n";

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

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

cout << "TP " << TP << "\n"; //👈Human(人間)型のキャラクターだけに備わっているテクニックポイントを表示することができます

}


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();


};



//👇🌞🌞🌞子クラス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 = 8;

Lyliane.TP = 5;




Dragon Pokky;


Pokky.name = "ポッキー";

Pokky.HP = 20;

Pokky.MP = 3;

Pokky.DP = 2;



Elf Sylphine;


Sylphine.name = "シルフィ";

Sylphine.HP = 5;

Sylphine.MP = 8;

Sylphine.EP = 15;




GameCharacter* a;


a = &Pokky;


a->statusDataDisplay();



a = &Lyliane;


a->statusDataDisplay();



a = &Sylphine;


a->statusDataDisplay();




return 0;

}


プログラムの実行結果


ポッキー

HP 20

MP 3

DP 2

リリアーネ

HP 10

MP 8

TP 5

シルフィ

HP 5

MP 8

DP 15



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



Human Lyliane;


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

Lyliane.HP = 10;

Lyliane.MP = 8;

Lyliane.TP = 5;




Dragon Pokky;


Pokky.name = "ポッキー";

Pokky.HP = 20;

Pokky.MP = 3;

Pokky.DP = 2;



Elf Sylphine;


Sylphine.name = "シルフィ";

Sylphine.HP = 5;

Sylphine.MP = 8;

Sylphine.EP = 15;


を実行したのち


親クラスGameCharacter*型のポインタ変数宣言


GameCharacter* a;


を実行しています


こうして作成された



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


a = &Pokky;



  🌞子クラスDragon型のオブジェクトPokkyのアドレス&Pokky🌞


を代入すると



a->statusDataDisplay();


の実行の際


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



純粋仮想関数で


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


によってオーバーライドされているので


GameCharacter*型のポインタ変数aは


親クラスGameCharacterのメンバ関数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


が代入されたものが実行されることになります


ですので


コマンドプロンプト画面に


ポッキー

HP 20

MP 3

DP 2


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



次に


GameCharacter*型のポインタ変数aに


a = &Lyliane;



子クラスHuman型のオブジェクトLylianeのアドレス&Lylianeを代入すると


a->statusDataDisplay();


の実行の際


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



純粋仮想関数で


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


によってオーバーライドされているので





a->statusDataDisplay();


の実行の際


GameCharacter*型のポインタ変数aは


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


でなく


子クラスHumanのメンバ関数statusDataDisplay()の定義

👇

void Human::statusDataDisplay() {


cout << name << "\n";

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

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

cout << "TP " << TP << "\n"; //👈Human(人間)型のキャラクターだけに備わっているテクニックポイントを表示することができます

}

👆

にアクセスすることになり


name

HP

MP

TP


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

Lyliane.name

Lyliane.HP

Lyliane.MP

Lyliane.TP


が代入されたものが実行されることになります


ですので


コマンドプロンプト画面に


リリアーネ

HP 10

MP 8

TP 5


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



次に


GameCharacter*型のポインタ変数aに


a = &Sylphine;



子クラスElf型のオブジェクトSylphineのアドレス&Sylphineを代入すると


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



純粋仮想関数で


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


によってオーバーライドされているので




a->statusDataDisplay();


の実行の際


GameCharacter*型のポインタ変数aは


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


でなく


子クラスElfのメンバ関数statusDataDisplay()の定義

👇

void Elf::statusDataDisplay() {


cout << name << "\n";

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

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

cout << "EP " << EP << "\n";//👈エルフ型のキャラクターだけに備わっているエルフポイントを表示することができます

}

👆

にアクセスすることになり


name

HP

MP

EP


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


Sylphine.name

Sylphine.HP

Sylphine.MP

Sylphine.DP


が代入されたものが実行されることになります


ですので


コマンドプロンプト画面に


シルフィ

HP 5

MP 8

TP 15


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



つまり


a->statusDataDisplay();


の実行の際


ポインタ変数aに代入されるアドレスを


&Pokky

&Lyliane

&Sylphine


と変更するだけで


実行される関数を入れ替えることができるというわけです



            このことを



           ポリモーフィズム(多態性)


といいます」





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

作者を応援しよう!

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

応援したユーザー

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

新規登録で充実の読書を

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

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

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