🌻天国にいけるC++言語入門🌻 進化し続けるオブジェクト指向プログラミング ver3.2307
仮想関数を使わなければHuman(人間)型のゲームキャラクターの相手のステータスデータを読み取るスキャンという能力は子クラス型オブジェクトの(親クラスの)メンバ変数のデータしか読み取れません
仮想関数を使わなければHuman(人間)型のゲームキャラクターの相手のステータスデータを読み取るスキャンという能力は子クラス型オブジェクトの(親クラスの)メンバ変数のデータしか読み取れません
ソーラー「今度は
さらに
新たに
親クラスGameCharacterを継承した
子クラスElfのクラス宣言とそのメンバ関数statusDataDisplay()
を以下のように
設定し登場させてみたいと思います
👇
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";//🌞エルフポイントEPを表示しています
}
ソーラー「
親クラスGameCharacterを継承した子クラスDragon
につづいて
親クラスGameCharacterを継承した
この子クラスElfを追加して用いて
子クラスHuman型のキャラクターであるリリアーネが
子クラスDragon型のキャラクターである ポッキー
子クラスElf型のキャラクターである シルフィ
のステータスデータ
を読み取る
ことを表現したプログラムを実行してみましょう
そのプログラムはこちらです
👇
#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の子クラスHuman型のオブジェクト宣言
Human Lyliane;
を実行し
Human(人間)型のゲームキャラクター リリアーネ
の
名前 リリアーネ
HP 10
MP 5
TP 7
を
子クラスHuman型のオブジェクトLylianeのメンバ変数
Lyliane.name
Lyliane.HP
Lyliane.MP
Lyliane.TP
に
Lyliane.name = "リリアーネ";
Lyliane.HP = 10;
Lyliane.MP = 5;
Lyliane.TP = 7;
と代入しています
次に
Pokkyの子クラスDragon型のオブジェクト宣言
Dragon Pokky;
を実行し
Dragon(ドラゴン)型のゲームキャラクター ポッキー
の
名前 ポッキー
HP 20
MP 3
DP 2
を
子クラスDragon型のオブジェクトPokkyのメンバ変数
Pokky.name
Pokky.HP
Pokky.MP
Pokky.DP
に
Pokky.name = "ポッキー";
Pokky.HP = 20;
Pokky.MP = 3;
Pokky.DP = 2;
と代入しています
さらに
Silphyの子クラスElf型のオブジェクト宣言
Elf Silphy;
を実行し
Elf(エルフ)型のゲームキャラクター シルフィ
の
名前 シルフィ
HP 3
MP 18
EP 3
を
子クラスElf型のオブジェクトSilphyのメンバ変数
Silphy.name
Silphy.HP
Silphy.MP
Silphy.EP
に
Silphy.name = "シルフィ";
Silphy.HP = 3;
Silphy.MP =18;
Silphy.EP=3;
と代入しています
さあ、そして いよいよ
子クラスHuman型のオブジェクトLylianeのメンバ変数
Lyliane.scanGameCharacterData(Pokky);
の実行ですね
Lyliane.scanGameCharacterData(Pokky);
が実行されると
👇子クラスHumanのメンバ関数
scanGameCharacterData(GameCharacter& a)の定義
void Human::scanGameCharacterData(GameCharacter& a) {
cout << "スキャン発動!" << "\n";
cout << name << "は" << a.name << "のスキャンを開始した" << "\n";
cout << "ステータスデータ" << "\n";
a.statusDataDisplay();
}
の
親クラスGameCharacter&型の参照変数宣言
💖GameCharacter& a💖
に
🍎子クラスDragon型のオブジェクトPokky🍎
が代入されます
この場合
親クラスGameCharacter&の参照変数aでは
子クラスDragon型のオブジェクトPokkyの(親クラスGameCharacterから引き継いだ)メンバ変数
Pokky.name
Pokky.HP
Pokky.MP
子クラスDragon型のオブジェクトPokkyの(親クラスGameCharacterから引き継いだ)メンバ関数
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();
}
の
name にはLyliane.name
a.name にはPokky.name
が代入され
a.statusDataDisplay();
の部分は
Pokky.statusDataDisplay();
に等しいものが実行されることになります
つまり
cout << "スキャン発動!" << "\n";
cout << Lyliane.name << "は" << Pokky.name << "のスキャンを開始した" << "\n";
cout << "ステータスデータ" << "\n";
Pokky.statusDataDisplay();
が実行されることになります
この
💖Pokky.statusDataDisplay();💗
の実行においては
子クラスDragon型のオブジェクトPokkyの(親クラスGameCharacterから引き継いだ)メンバ関数
Pokky.statusDataDisplay();
が実行されることになります
ですのでコマンドプロンプト画面に
スキャン発動!
リリアーネはポッキーのスキャンを開始した
ステータスデータ
ポッキー
HP 20
MP 3
が表示されることになります
次に
Lyliane.scanGameCharacterData(Silphy);
が実行されると
👇クラスHumanのメンバ関数scanGameCharacterData(GameCharacter& a)の定義
void Human::scanGameCharacterData(GameCharacter& a) {
cout << "スキャン発動!" << "\n";
cout << name << "は" << a.name << "のスキャンを開始した" << "\n";
cout << "ステータスデータ" << "\n";
a.statusDataDisplay();
}
の
親クラスGameCharacter&の参照変数宣言
💖GameCharacter& a💖
に
🍎子クラスElf型のオブジェクトSilphy🍎
が代入されます
この場合
親クラスGameCharacter&の参照変数aでは
子クラスElf型のオブジェクトSilphyの(親クラスGameCharacterから引き継いだ)メンバ変数
Silphy.name
Silphy.HP
Silphy.MP
子クラスElf型のオブジェクトSilphyの(親クラスGameCharacterから引き継いだ)メンバ関数
Silphy.statusDataDisplay()
の管理しているメモリ領域にのみアクセスすることができます
ですので
Lyliane.scanGameCharacterData(Silphy);
が実行されると
👇クラス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 にはSilphy.name
が代入され
a.statusDataDisplay();
の部分は
Silphy.statusDataDisplay();
に等しいものが実行されることになります
つまり
cout << "スキャン発動!" << "\n";
cout << Lyliane.name << "は" << Silphy.name << "のスキャンを開始した" << "\n";
cout << "ステータスデータ" << "\n";
Silphy.statusDataDisplay();
が実行されることになります
この
💖Silphy.statusDataDisplay();💖
の実行においては
子クラスElf型のオブジェクトSilphyの(親クラスGameCharacterから引き継いだ)メンバ関数
Silphy.statusDataDisplay();
が実行されることになります
ですので
コマンドプロンプト画面に
スキャン発動!
リリアーネはシルフィのスキャンを開始した
ステータスデータ
シルフィ
HP 3
MP 18
が表示されることになります
次に
Lyliane.scanGameCharacterData(Lyliane);
の実行ですね
Lyliane.scanGameCharacterData(Lyliane);
が実行されると
👇子クラスHumanのメンバ関数scanGameCharacterData(GameCharacter& a)の定義
void Human::scanGameCharacterData(GameCharacter& a) {
cout << "スキャン発動!" << "\n";
cout << name << "は" << a.name << "のスキャンを開始した" << "\n";
cout << "ステータスデータ" << "\n";
a.statusDataDisplay();
}
の
親クラスGameCharacter&の参照変数宣言
💖GameCharacter& a💖
に
🍎子クラスHuman型のオブジェクトLyliane🍎
が代入されます
この場合
親クラスGameCharacter&の参照変数aでは
子クラスHuman型のオブジェクトLylianeの(親クラスGameCharacterから引き継いだ)メンバ変数
Lyliane.name
Lyliane.HP
Lyliane.MP
子クラスHuman型のオブジェクトLylianeの(親クラスGameCharacterから引き継いだ)メンバ関数
Lyliane.statusDataDisplay()
の管理しているメモリ領域にのみアクセスすることができます
ですので
Lyliane.scanGameCharacterData(Lyliane);
が実行されると
👇クラス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 にはLyliane.name
が代入され
a.statusDataDisplay();
の部分は
Lyliane.statusDataDisplay();
に等しいものが実行されることになります
つまり
cout << "スキャン発動!" << "\n";
cout << Lyliane.name << "は" << Lyliane.name << "のスキャンを開始した" << "\n";
cout << "ステータスデータ" << "\n";
Lyliane.statusDataDisplay();
が実行されることになります
この
💖Lyliane.statusDataDisplay();💖
の実行においては
子クラスHuman型のオブジェクトLylianeの(親クラスGameCharacterから引き継いだ)メンバ関数
Lyliane.statusDataDisplay();
が実行されることになります
ですので
コマンドプロンプト画面に
スキャン発動!
リリアーネはリリアーネのスキャンを開始した
ステータスデータ
リリアーネ
HP 10
MP 5
が表示されることになりますね(^_-)-☆」
マックス「Oh,
どうやら
Human型のキャラクターは
他のキャラクターのステータスデータを
読み取る能力が設定されたみたいだな」
ソーラー「そうですね
ですが
ここで気付くことがあります」
マックス「ひょっとこ?気付くこと?」
ソーラー「詳しくは
もう1度
プログラムの実行結果をご覧ください」
👇
プログラムの実行結果
スキャン発動!
リリアーネはポッキーのスキャンを開始した
ステータスデータ
ポッキー
HP 20
MP 3
スキャン発動!
リリアーネはシルフィのスキャンを開始した
ステータスデータ
シルフィ
HP 3
MP 18
スキャン発動!
リリアーネはリリアーネのスキャンを開始した
ステータスデータ
リリアーネ
HP 10
MP 5
マックス「気付くこと???」
てんC「そういえば
Human型のキャラクター リリアーネは
Human型のキャラクター特有のステータスデータ
TP 7
Dragon型のキャラクター ポッキーは
Dragon型のキャラクター特有のステータスデータ
DP 2
Elf型のキャラクター シルフィは
Elf型のキャラクター特有のステータスデータ
EP 3
をもっているのですが
それが表示されていませんね
」
マックス「おおぅ ほんとだ
あれ?????
子クラスHumanの
親クラスGameCharacterのメンバ関数
statusDataDisplay()を
オーバーライドしているメンバ関数statusDataDisplay()の定義は
void Human::statusDataDisplay() {
cout << name << "\n";
cout << "HP " << HP << "\n";
cout << "MP " << MP << "\n";
cout << "TP " << TP << "\n";//🌞TPを表示します
}
なのにな
って
Lyliane.scanGameCharacterData(Lyliane);
が実行されると
以下の命令文が実行されることになるが
👇
cout << "スキャン発動!" << "\n";
cout << Lyliane.name << "は" << Lyliane.name << "のスキャンを開始した" << "\n";
cout << "ステータスデータ" << "\n";
Lyliane.statusDataDisplay();
👆
この
💖Lyliane.statusDataDisplay();💖
が実行されるときは
親クラスGameCharacterのメンバ関数statusDataDisplay()の定義
が用いられたものが実行されるんだろう
親クラスGameCharacterのメンバ関数statusDataDisplay()の定義
👇
void GameCharacter::statusDataDisplay() {
cout << name << "\n";
cout << "HP " << HP << "\n";
cout << "MP " << MP << "\n";
}
👆
の
name
HP
MP
に
Lyliane.name
Lyliane.HP
Lyliane.MP
が代入されたものが実行されるのだから
リリアーネ
HP 10
MP 5
が表示されるだけで
リリアーネの
ステータスデータ
TP 7
が表示されるわけがないってか・・・
まあ、そうなるよな
じゃあ
コマンドプロンプト画面に
リリアーネ
HP 10
MP 5
TP 7
を表示させるには
今のプログラムの
cout << "スキャン発動!" << "\n";
cout << Lyliane.name << "は" << Lyliane.name << "のスキャンを開始した" << "\n";
cout << "ステータスデータ" << "\n";
Lyliane.statusDataDisplay();
の中の
Lyliane.statusDataDisplay();
が実行されるとき
親クラスGameCharacterのメンバ関数statusDataDisplay()の定義
が用いられた
子クラスHuman型のオブジェクトLylianeの(親クラスから引き継いだ)メンバ関数
Lyliane.statusDataDisplay();
でなく
子クラスHumanのオーバーライドしているメンバ関数statusDataDisplay()の定義
が用いられた
子クラスHuman型のオブジェクトLylianeの(子クラスに備わっている)メンバ関数
Lyliane.statusDataDisplay();
が実行されるようにすれば
👇子クラスHumanのオーバーライドしているメンバ関数statusDataDisplay() の定義の
void Human::statusDataDisplay() {
cout << name << "\n";
cout << "HP " << HP << "\n";
cout << "MP " << MP << "\n";
cout << "TP " << TP << "\n";
}
👆
の
name
HP
MP
TP
に
Lyliane.name
Lyliane.HP
Lyliane.MP
Lyliane.TP
が代入されたものが実行されるのだから
リリアーネ
HP 10
MP 5
TP 7
が表示されるんじゃないか?
ってどうやったら そんなことが可能なんだ??
Lyliane.scanGameCharacterData(Lyliane);
が実行されると
👇クラスHumanのメンバ関数scanGameCharacterData(GameCharacter& a)の定義
void Human::scanGameCharacterData(GameCharacter& a) {
cout << "スキャン発動!" << "\n";
cout << name << "は" << a.name << "のスキャンを開始した" << "\n";
cout << "ステータスデータ" << "\n";
a.statusDataDisplay();
}
の
親クラスGameCharacter&型の参照変数 宣言
💖GameCharacter& a💖
に
🍎子クラスHuman型のオブジェクトLyliane🍎
が代入される
!!が!!
💖GameCharacter&型の参照変数 a💖
では
子クラスHuman型のオブジェクトLylianeの(親クラスから引き継いだ)メンバ変数
Lyliane.name
Lyliane.HP
Lyliane.MP
子クラスHuman型のオブジェクトLylianeの(親クラスから引き継いだ)メンバ関数
Lyliane.statusDataDisplay()
の管理するメモリ領域にしかアクセスすることはできないんんん・・・
ということは
Lyliane.scanGameCharacterData(Lyliane);
が実行されると
👇子クラス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 にもLyliane.name
が代入され
a.statusDataDisplay();
は
Lyliane.statusDataDisplay();
が実行されることになるが
💖Lyliane.statusDataDisplay();💖
は
子クラスHuman型のオブジェクトLylianeの(親クラスから引き継いだ)メンバ関数
Lyliane.statusDataDisplay()
を実行してしまうことになる
子クラスHuman型のオブジェクトLylianeの(親クラスのメンバ関数statusDataDisplay()をオーバーライドしている子クラスに備わっている)メンバ関数
Lyliane.statusDataDisplay()
が実行されることはないいぃぃ
んもぉう(´▽`*)
どうしたらいいのおん?」
ソーラー「ここで登場するのが
😊仮想関数😊
なんです」
マックス「・・??って
ちょっとまったああ😊
今思いつきそうぅぅ
👇子クラスHumanのメンバ関数scanGameCharacterData(GameCharacter& a)の定義
void Human::scanGameCharacterData(GameCharacter& a) {
cout << "スキャン発動!" << "\n";
cout << name << "は" << a.name << "のスキャンを開始した" << "\n";
cout << "ステータスデータ" << "\n";
a.statusDataDisplay();
}
の
引数となっている
GameCharacter& a
を
Human& a
に変えればいいんじゃないか?(*´▽`*)
やったか?
その場合
Lyliane.scanGameCharacterData(Lyliane);
が実行されると
👇子クラスHumanのメンバ関数scanGameCharacterData(Human& a)の定義
void Human::scanGameCharacterData(Human& a) {
cout << "スキャン発動!" << "\n";
cout << name << "は" << a.name << "のスキャンを開始した" << "\n";
cout << "ステータスデータ" << "\n";
a.statusDataDisplay();
}
の
💖Human& a💖
に
🍎子クラスHuman型のオブジェクトLyliane🍎
が代入されるだろぉ
もうそのまんま\(^o^)/いぇ~い
ということは
Lyliane.scanGameCharacterData(Lyliane);
が実行されると
👇子クラスHumanのメンバ関数scanGameCharacterData(Human& a)の定義
void Human::scanGameCharacterData(Human& a) {
cout << "スキャン発動!" << "\n";
cout << name << "は" << a.name << "のスキャンを開始した" << "\n";
cout << "ステータスデータ" << "\n";
a.statusDataDisplay();
}
の
name にはLyliane.name
a.name にもLyliane.name
が代入され
a.statusDataDisplay();
は
Lyliane.statusDataDisplay();
を表すことになるが
Human& a
に
Lyliane
が代入されている状態では
aは子クラスHuman型のオブジェクトLylianeそのものであり
Lylianeは子クラスHuman型のオブジェクトなので
Lyliane.statusDataDisplay();
の実行においては
子クラスHumanの
親クラスGameCharacterのメンバ関数statusDataDisplay()
を
オーバーライドしている子クラスHumanのメンバ関数statusDataDisplay()の定義が用いられた
子クラスHuman型のオブジェクトLylianeの(《《親クラスGameCharacterのメンバ関数statusDataDisplay()
を
オーバーライドしている子クラスHumanの》》)メンバ関数
😊Lyliane.statusDataDisplay()😊
が実行されることになる
すると
子クラスHumanのメンバ関数statusDataDisplay()の定義
👇
void Human::statusDataDisplay() {
cout << name << "\n";
cout << "HP " << HP << "\n";
cout << "MP " << MP << "\n";
cout << "DP " << DP << "\n";
}
👆
の
name
HP
MP
DP
に
Lyliane.name
Lyliane.HP
Lyliane.MP
Lyliane.DP
が代入されたものが実行されるのだから
リリアーネ
HP 10
MP 5
TP 7
が表示される💖
めでたし、めでたしってわけだ\(^o^)/ やあったなあっ😊
(嘘^^だよ~~ん)
子クラスHumanのクラス宣言内のメンバ関数宣言を
👇ここです
void scanGameCharacterData(GameCharacter& a);
から 👇ここです
void scanGameCharacterData(Human& a);
へ
子クラスHumanのメンバ関数の定義を
👇ここです
void Human::scanGameCharacterData(GameCharacter& a) {
cout << "スキャン発動!" << "\n";
cout << name << "は" << a.name << "のスキャンを開始した" << "\n";
cout << "ステータスデータ" << "\n";
a.statusDataDisplay();
}
から
👇ここです
void Human::scanGameCharacterData(Human& a) {
cout << "スキャン発動!" << "\n";
cout << name << "は" << a.name << "のスキャンを開始した" << "\n";
cout << "ステータスデータ" << "\n";
a.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";
}
class Human :public GameCharacter {
public:
int TP;;//👈Human(人間)型のキャラクターだけに備わっているテクニックポイントです
void statusDataDisplay();//🌞親クラスGameCharacterのメンバ関数statusDataDisplay()をオーバーライドしています
void scanGameCharacterData(Human& 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(Human& 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;
}
プログラムの実行結果
エラー (アクティブ) E0434 型 "Human &" の参照 (const で修飾されていない) は型 "Elf" の値では初期化できません
エラー (アクティブ) E0434 型 "Human &" の参照 (const で修飾されていない) は型 "Dragon" の値では初期化できません
エラー C2664 'void Human::scanGameCharacterData(Human &)': 引数 1 を 'Elf' から 'Human &' へ変換できません。
エラー C2664 'void Human::scanGameCharacterData(Human &)': 引数 1 を 'Dragon' から 'Human &' へ変換できません。
マックス「おおおぅ 何でビルド実行できん!?」
ソーラー「それは
子クラスHumanのメンバ関数scanGameCharacterData(Human& a)の定義のように
👇
void Human::scanGameCharacterData(Human& a) {
cout << "スキャン発動!" << "\n";
cout << name << "は" << a.name << "のスキャンを開始した" << "\n";
cout << "ステータスデータ" << "\n";
a.statusDataDisplay();
}
👆
子クラスHumanのメンバ関数scanGameCharacterData(Human& a)の引数部分が
Human& a
に設定されていると
子クラスDragon型のオブジェクトPokky
子クラスElf型のオブジェクトSylphy
を
Human& a
に代入することができなくなってしまうからなんです
ですので
Human& a
に
子クラスDragon型のオブジェクトPokky
子クラスElf型のオブジェクトSylphy
を代入することができないのに
Lyliane.scanGameCharacterData(Pokky);
Lyliane.scanGameCharacterData(Sylphy);
を実行しようとすると
ビルドエラー
エラー (アクティブ) E0434 型 "Human &" の参照 (const で修飾されていない) は型 "Elf" の値では初期化できません
エラー (アクティブ) E0434 型 "Human &" の参照 (const で修飾されていない) は型 "Dragon" の値では初期化できません
エラー C2664 'void Human::scanGameCharacterData(Human &)': 引数 1 を 'Elf' から 'Human &' へ変換できません。
エラー C2664 'void Human::scanGameCharacterData(Human &)': 引数 1 を 'Dragon' から 'Human &' へ変換できません。
が表示されることになるんだね」
新規登録で充実の読書を
- マイページ
- 読書の状況から作品を自動で分類して簡単に管理できる
- 小説の未読話数がひと目でわかり前回の続きから読める
- フォローしたユーザーの活動を追える
- 通知
- 小説の更新や作者の新作の情報を受け取れる
- 閲覧履歴
- 以前読んだ小説が一覧で見つけやすい
アカウントをお持ちの方はログイン
ビューワー設定
文字サイズ
背景色
フォント
組み方向
機能をオンにすると、画面の下部をタップする度に自動的にスクロールして読み進められます。
応援すると応援コメントも書けます