🌻天国にいけるC++言語入門🌻 進化し続けるオブジェクト指向プログラミング ver3.2307
親クラスのクラス宣言内でアクセス指定子がpublicに設定された親クラスのメンバ変数、メンバ関数をアクセス指定子protectedを使って子クラスへ継承してみます
親クラスのクラス宣言内でアクセス指定子がpublicに設定された親クラスのメンバ変数、メンバ関数をアクセス指定子protectedを使って子クラスへ継承してみます
ソーラー「今度は
親クラスGameCharacterのメンバ変数宣言
string name;
int HP;
int MP;
親クラスGameCharacterのメンバ関数宣言
void statusDataDisplay();
のアクセス指定子はpublicのまま
class Dragon:protected GameCharacter
のように
アクセス指定子
protected
を用いて
親クラスGameCharacterから
子クラスDragonへ
クラスの継承を行ってみたいと思います
マックス「protected?
そんな アクセス指定子あったか?」
solarplexuss(・・・ありました・・・・・)
ソーラー「アクセス指定子
🐤protected🐤
は
親クラスから子クラスへ
クラスの継承を行う際に
カプセル化を行うために
💖親クラスのメンバ変数宣言💖に
用いられる
アクセス指定子なんです
が
🐤今日は🐤
親クラスGameCharacterのメンバ変数宣言
string name;
int HP;
int MP;
親クラスGameCharacterのメンバ関数宣言
void statusDataDisplay();
のアクセス指定子がpublicに設定された状態で
class Dragon:
のように
アクセス指定子
protected
を用いて
親クラスGameCharacterから
子クラスDragonへ
クラスの継承を行ってみたいと思います
(結局はカプセル化がおこなわれることになるのですが・・・)
class Dragon:
のように
アクセス指定子
protected
が設定された状態で
まずは恒例の
main関数内で
Lylianeの親クラスGameCharacter型のオブジェクト宣言
GameCharacter Lyliane;
だけを実行してみたいと思います。
ポイントは
🌞🌞親クラスGameCharacter🌞🌞
というところです。
Lylianeの親クラスGameCharacter型のオブジェクト宣言
GameCharacter Lyliane;
を実行した場合
生成されるのは親クラスGameCharacter型のオブジェクトLylianeです
もちろん
関係してくるのは
🌞🌞親クラスGameCharacter🌞🌞
のみで
子クラスDragon
は関係してきません。
そのプログラムはこっちだね。」
👇
#include <iostream>
#include <string>//文字列を取り扱うためにヘッダファイル <string>をインクルードしています
using namespace std;
//👇🌞🌞🌞クラスGameCharacterです🌞🌞🌞
class GameCharacter {
public:
string name;
int HP;
int MP;
void statusDataDisplay();
//クラスGameCharacterにはuseFireRecovery(GameCharacter& a)を設定しません
};
void GameCharacter::statusDataDisplay() {
cout << name << "\n";
cout << "HP " << HP << "\n";
cout << "MP " << MP << "\n";
}
//👇🌞🌞🌞クラスGameCharacterを継承したクラスDragonです🌞🌞🌞
class Dragon:protected GameCharacter {
public:
void useFireRecovery(GameCharacter& a);
};
void Dragon::useFireRecovery(GameCharacter& a) {
cout << name << "は灼熱のフレアを" << a.name << "に吐いた !" << "\n";
cout << a.name << "は灼熱のフレアを受け燃え上がった!" << "\n";
a.HP += 10;
cout << a.name << "の体力は10回復した" << "\n";
}
int main() {
GameCharacter Lyliane;
Lyliane.name = "リリアーネ";
Lyliane.HP = 10;
Lyliane.MP = 8;
Lyliane.statusDataDisplay();
return 0;
}
プログラムの実行結果
リリアーネ
HP 10
MP 8
マックス「クラスの継承を
アクセス指定子
protected
を用いた
class Dragon:protected GameCharacter
の場合と
アクセス指定子
public
private
を用いた
class Dragon:public GameCharacter
class Dragon:private GameCharacter
の場合とで
プログラムの実行結果が同じになってないか?」
ソーラー「そうなんです。 それもそのはずです。
なぜならこのプログラムでは継承は関係してこないからです
アクセス指定子
public
private
protected
を用いて
親クラスGameCharacterから
子クラスDragonへ
class Dragon:public GameCharacter
class Dragon:private GameCharacter
class Dragon:protected GameCharacter
のように
クラスの継承を行った場合
アクセス指定子がpublicに設定された
親クラスGameCharacterのメンバ変数宣言
string name;
int HP;
int MP;
親クラスGameCharacterのメンバ関数宣言
void statusDataDisplay();
は
親クラスGameCharacterのメンバ変数宣言
string name;
int HP;
int MP;
親クラスGameCharacterのメンバ関数宣言
void statusDataDisplay();
の
アクセス指定子がpublicに変更された状態で
アクセス指定子がprvateに変更された状態で
アクセス指定子がprotectedに変更された状態で
子クラスDragonのクラス宣言内に
💖必ず引き継がれる💖
子クラスDragonのクラス宣言内に
💖記述されている💖
ことになります
親クラスGameCharacterのメンバ変数宣言
string name;
int HP;
int MP;
親クラスGameCharacterのメンバ関数宣言
void statusDataDisplay();
は
class Dragon:public GameCharacter
なら
子クラスDragonのクラス宣言内に
引き継がれ(記述され)
class Dragon:private GameCharacter
なら
子クラスDragonのクラス宣言内に
引き継がれない(記述されない)ということはありません」
マックス「なにぃぃぃ
なんか微妙ぃぞぉ!?
ちょっとまてよ
以前のエピソードで
親クラスGameCharacterのメンバ変数宣言
string name;
int HP;
int MP;
親クラスGameCharacterのメンバ関数宣言
void statusDataDisplay();
のアクセス指定子が
🌞private🌞
(眩しい)
の場合に
親クラスGameCharacterから
子クラスDragonへ
class Dragon:public GameCharacter
のように
継承を行った場合は
親クラスGameCharacterのメンバ変数宣言
string name;
int HP;
int MP;
親クラスGameCharacterのメンバ関数宣言
void statusDataDisplay();
は
子クラスDragonのクラス宣言内に引き継がれなかったような気がするんだが・・・
だから
子クラスDragonのメンバ関数の定義内で
親クラスGameCharacterのメンバ変数
name
HP
MP
が用いられているだけで
プログラムの実行時
ビルドエラーが表示されなかったか?」
ソーラー「そう ここが
class Dragon:public GameCharacter
class Dragon:private GameCharacter
class Dragon:protected GameCharacter
を行って
クラスの継承を行うときの最大のポイントといえるかな
ここがわかればクラスの継承マスターです
class Dragon:public GameCharacter
class Dragon:private GameCharacter
class Dragon:protected GameCharacter
には
アクセス指定子がpublicに設定された
親クラスGameCharacterのメンバ変数宣言
string name;
int HP;
int MP;
親クラスGameCharacterのメンバ関数宣言
void statusDataDisplay();
を
子クラスDragonのクラス宣言内に引き継がれないようにする機能はありません
引き継がれるのは確定で
class Dragon:public GameCharacter
class Dragon:private GameCharacter
class Dragon:protected GameCharacter
のようにクラスの継承がおこなわれたとき
親クラスGameCharacterのメンバ変数宣言
string name;
int HP;
int MP;
親クラスGameCharacterのメンバ関数宣言
void statusDataDisplay();
のアクセス指定子は
それぞれ
public
private
protected
になった状態
すなわち
public:
string name;
int HP;
int MP;
void statusDataDisplay();
private:
string name;
int HP;
int MP;
void statusDataDisplay();
protected:
string name;
int HP;
int MP;
void statusDataDisplay();
になった状態で
子クラスDragonのクラス宣言内に引き継がれる
記述されることになります
(結局
💖親クラスGameCharacterのメンバ変数宣言💖
string name;
int HP;
int MP;
💖親クラスGameCharacterのメンバ関数宣言💖
void statusDataDisplay();
のアクセス指定子が
publicであるか
privateであるか
protectedであるかが
子クラスDragonのクラス宣言内に
親クラスGameCharacterのメンバ変数宣言
string name;
int HP;
int MP;
親クラスGameCharacterのメンバ関数宣言
void statusDataDisplay();
が引き継がれるかどうかに
かかわってきます
継承方法の
class Dragon:public GameCharacter
class Dragon:private GameCharacter
class Dragon:protected GameCharacter
は関係してきません
親クラスGameCharacterのメンバ変数宣言
string name;
int HP;
int MP;
親クラスGameCharacterのメンバ関数宣言
void statusDataDisplay();
のアクセス指定子が
private
の場合は
親クラスGameCharacterのメンバ変数宣言
string name;
int HP;
int MP;
親クラスGameCharacterのメンバ関数宣言
void statusDataDisplay();
は
子クラスDragonのクラス宣言内に引き継がれません
試しに
親クラスGameCharacterのメンバ変数宣言
string name;
int HP;
int MP;
親クラスGameCharacterのメンバ関数宣言
void statusDataDisplay();
のアクセス指定子が
private
に設定された状態で
class Dragon:public GameCharacter
のようにアクセス指定子publicを使ってクラスの継承を行ってみます
そのプログラムはこちらです
👇
#include <iostream>
#include <string>//文字列を取り扱うためにヘッダファイル <string>をインクルードしています
using namespace std;
//👇🌞🌞🌞クラスGameCharacterです🌞🌞🌞
class GameCharacter {
private:
string name;
int HP;
int MP;
void statusDataDisplay();
};
void GameCharacter::statusDataDisplay() {
cout << name << "\n";
cout << "HP " << HP << "\n";
cout << "MP " << MP << "\n";
}
//👇🌞🌞🌞クラスGameCharacterを継承したクラスDragonです🌞🌞🌞
class Dragon :public GameCharacter {
public:
void statusDataDisplay2(string a, int b, int c);
};
void Dragon::statusDataDisplay2(string a, int b, int c) {
name = a;
HP = b;
MP = c;
cout << name << "\n";
cout << "HP " << HP << "\n";
cout << "MP " << MP << "\n";
}
int main() {
}
プログラムの実行結果
重大度レベル コード 説明 プロジェクト ファイル 行 抑制状態
エラー (アクティブ) E0265 メンバー "GameCharacter::name" (宣言された 行 9) にアクセスできません
エラー (アクティブ) E0265 メンバー "GameCharacter::name" (宣言された 行 9) にアクセスできません
エラー (アクティブ) E0265 メンバー "GameCharacter::MP" (宣言された 行 11) にアクセスできません
エラー (アクティブ) E0265 メンバー "GameCharacter::MP" (宣言された 行 11) にアクセスできません
エラー (アクティブ) E0265 メンバー "GameCharacter::HP" (宣言された 行 10) にアクセスできません
エラー (アクティブ) E0265 メンバー "GameCharacter::HP" (宣言された 行 10) にアクセスできません
エラー C2248 'GameCharacter::name': private メンバー (クラス 'GameCharacter' で宣言されている) にアクセスできません。
エラー C2248 'GameCharacter::name': private メンバー (クラス 'GameCharacter' で宣言されている) にアクセスできません。
エラー C2248 'GameCharacter::MP': private メンバー (クラス 'GameCharacter' で宣言されている) にアクセスできません。
エラー C2248 'GameCharacter::MP': private メンバー (クラス 'GameCharacter' で宣言されている) にアクセスできません。
エラー C2248 'GameCharacter::HP': private メンバー (クラス 'GameCharacter' で宣言されている) にアクセスできません。
エラー C2248 'GameCharacter::HP': private メンバー (クラス 'GameCharacter' で宣言されている) にアクセスできません。
ソーラー「main関数内に何も記述されていないのに
ビルドエラーが表示されています
このエラーは
親クラスGameCharacterのメンバ変数宣言
string name;
int HP;
int MP;
親クラスGameCharacterのメンバ関数宣言
void statusDataDisplay();
が
子クラスDragonに引き継がれていないために
起こっています
親クラスGameCharacterのメンバ変数宣言
string name;
int HP;
int MP;
親クラスGameCharacterのメンバ関数宣言
void statusDataDisplay();
が
子クラスDragonのクラス宣言内に引き継がれていないのに
子クラスDragonのメンバ関数statusDataDisplay2(string a, int b, int c)
の定義内で
name
HP
MP
が記述されているため
ビルドエラーが表示されています
親クラスGameCharacterのメンバ変数宣言
string name;
int HP;
int MP;
親クラスGameCharacterのメンバ関数宣言
void statusDataDisplay();
のアクセス指定子が
protected
の場合は
親クラスGameCharacterのメンバ変数宣言
string name;
int HP;
int MP;
親クラスGameCharacterのメンバ関数宣言
void statusDataDisplay();
は
子クラスDragonのクラス宣言内に引き継がれることになります
親クラスGameCharacterのメンバ変数宣言
string name;
int HP;
int MP;
親クラスGameCharacterのメンバ関数宣言
void statusDataDisplay();
のアクセス指定子が
protectedに設定された状態で
class Dragon :public GameCharacter
のようにアクセス指定子publicを使ってクラスの継承を行ってみます
そのプログラムはこちらです
👇
#include <iostream>
#include <string>//文字列を取り扱うためにヘッダファイル <string>をインクルードしています
using namespace std;
//👇🌞🌞🌞クラスGameCharacterです🌞🌞🌞
class GameCharacter {
protected:
string name;
int HP;
int MP;
void statusDataDisplay();
};
void GameCharacter::statusDataDisplay() {
cout << name << "\n";
cout << "HP " << HP << "\n";
cout << "MP " << MP << "\n";
}
//👇🌞🌞🌞クラスGameCharacterを継承したクラスDragonです🌞🌞🌞
class Dragon :public GameCharacter {
public:
void statusDataDisplay2(string a, int b, int c);
};
void Dragon::statusDataDisplay2(string a, int b, int c) {
name = a;
HP = b;
MP = c;
cout << name << "\n";
cout << "HP " << HP << "\n";
cout << "MP " << MP << "\n";
}
int main() {
Dragon Pokky;
Pokky.statusDataDisplay2("ポッキー", 15, 5);
return 0;
}
プログラムの実行結果
(何も表示されませんが
プログラムの実行はできています)
ソーラー「main関数内に何も記述されていませんが
プログラムの実行はできています
このことは
親クラスGameCharacterのメンバ変数宣言
string name;
int HP;
int MP;
親クラスGameCharacterのメンバ関数宣言
void statusDataDisplay();
が
子クラスDragonに引き継がれていることをあらわしています
さらに
この場合は
次のようなプログラムを実行することが可能です
👇
#include <iostream>
#include <string>//文字列を取り扱うためにヘッダファイル <string>をインクルードしています
using namespace std;
//👇🌞🌞🌞クラスGameCharacterです🌞🌞🌞
class GameCharacter {
protected:
string name;
int HP;
int MP;
void statusDataDisplay();
};
void GameCharacter::statusDataDisplay() {
cout << name << "\n";
cout << "HP " << HP << "\n";
cout << "MP " << MP << "\n";
}
//👇🌞🌞🌞クラスGameCharacterを継承したクラスDragonです🌞🌞🌞
class Dragon :public GameCharacter {
public:
void statusDataDisplay2(string a, int b, int c);
};
void Dragon::statusDataDisplay2(string a, int b, int c) {
name = a;
HP = b;
MP = c;
cout << name << "\n";
cout << "HP " << HP << "\n";
cout << "MP " << MP << "\n";
}
int main() {
Dragon Pokky;
Pokky.statusDataDisplay2("ポッキー", 15, 5);
return 0;
}
プログラムの実行結果
ポッキー
HP 15
MP 5
(このプログラムではカプセル化がおこなわれています
詳しい解説はの・ち・ほ・ど💖)
ここで
さて お話はかわって
再び
親クラスGameCharacterのメンバ変数宣言
string name;
int HP;
int MP;
親クラスGameCharacterのメンバ関数宣言
void statusDataDisplay();
のアクセス指定子が
publicに設定された
次のプログラムをご覧ください
👇
#include <iostream>
#include <string>//文字列を取り扱うためにヘッダファイル <string>をインクルードしています
using namespace std;
//👇🌞🌞🌞クラスGameCharacterです🌞🌞🌞
class GameCharacter {
public:
string name;
int HP;
int MP;
void statusDataDisplay();
//クラスGameCharacterにはuseFireRecovery(GameCharacter& a)を設定しません
};
void GameCharacter::statusDataDisplay() {
cout << name << "\n";
cout << "HP " << HP << "\n";
cout << "MP " << MP << "\n";
}
//👇🌞🌞🌞クラスGameCharacterを継承したクラスDragonです🌞🌞🌞
class Dragon:protected GameCharacter {
public:
void useFireRecovery(GameCharacter& a);
};
void Dragon::useFireRecovery(GameCharacter& a) {
cout << name << "は灼熱のフレアを" << a.name << "に吐いた !" << "\n";
cout << a.name << "は灼熱のフレアを受け燃え上がった!" << "\n";
a.HP += 10;
cout << a.name << "の体力は10回復した" << "\n";
}
int main() {
GameCharacter Lyliane;
Lyliane.name = "リリアーネ";
Lyliane.HP = 10;
Lyliane.MP = 8;
Lyliane.statusDataDisplay();
return 0;
}
プログラムの実行結果
リリアーネ
HP 10
MP 8
このプログラムでは
class Dragon:protected GameCharacter
を行って
クラスの継承を行っていますが
アクセス指定子がpublicに指定された
親クラスGameCharacterのメンバ変数宣言
string name;
int HP;
int MP;
親クラスGameCharacterのメンバ関数宣言
void statusDataDisplay();
は
アクセス指定子がprotectedに書き換えられた状態で
子クラスDragonのクラス宣言内に引き継がれています
以下のようにです
👇
class Dragon:protected GameCharacter {
protected://👈🌞ここに注目
string name;
int HP;
int MP;
void statusDataDisplay();
public:
void useFireRecovery(GameCharacter& a);
};
クラスの継承を
class Dragon:public GameCharacter
class Dragon:private GameCharacter
class Dragon:protected GameCharacter
を用いて行った場合
親クラスGameCharacterのメンバ変数宣言
string name;
int HP;
int MP;
親クラスGameCharacterのメンバ関数宣言
void statusDataDisplay();
に設定されているアクセス指定子が
public
private
protected
に
変更されるものの
親クラスGameCharacterのメンバ変数宣言
string name;
int HP;
int MP;
親クラスGameCharacterのメンバ関数宣言
void statusDataDisplay();
は
子クラスDragonのクラス宣言内に引き継がれることになります
🌞ですので🌞
💖子クラスDragonのメンバ関数💖
💖useFireRecovery(GameCharacter& a) の定義内💖で
👇
void Dragon::useFireRecovery(GameCharacter& a) {
cout << name << "は灼熱のフレアを" << a.name << "に吐いた !" << "\n";
cout << a.name << "は灼熱のフレアを受け燃え上がった!" << "\n";
a.HP += 10;
cout << a.name << "の体力は10回復した" << "\n";
}
👆
のように
親クラスGameCharacterのメンバ変数
name
が用いられていても
プログラムの実行時にビルドエラーが表示されるようなことはありません
親クラスGameCharacterのメンバ変数宣言
string name;
は
アクセス指定子
public
private
protected
を用いて
class Dragon:public GameCharacter
class Dragon:private GameCharacter
class Dragon:protected GameCharacter
の
どのパターンで
クラスの継承が行われても
子クラスDragonのクラス宣言内に引き継がれるので
子クラスDragonのメンバ関数useFireRecovery(GameCharacter& a) の定義内で
もちいることができるというわけです
お話は戻って
main関数内で
親クラスGameCharacterを用いた
親クラスGameCharacter型のオブジェクト宣言
GameCharacter Lyliane;
を実行して
親クラスGameCharacter型のオブジェクトLyliane
を生成した場合
親クラスGameCharacterのメンバ変数宣言
string name;
int HP;
int MP;
親クラスGameCharacterのメンバ関数宣言
void statusDataDisplay();
に設定されているアクセス指定子は
🌞🌞🌞public🌞🌞🌞
なので
(親クラスGameCharacterから子クラスDragonへクラスの継承がおこなわれても
もちろん
元の
🌞親クラスGameCharacterのクラス宣言内の🌞
親クラスGameCharacterのメンバ変数宣言
string name;
int HP;
int MP;
親クラスGameCharacterのメンバ関数宣言
void statusDataDisplay();
に設定されているアクセス指定子は
🌞🌞🌞public🌞🌞🌞
のまま変化しません)
Lylianeの親クラスGameCharacter型のオブジェクト宣言
GameCharacter Lyliane;
を実行して
親クラスGameCharacter型のオブジェクトLylianeを作製したなら
親クラスGameCharacter型のオブジェクトLylianeのメンバ変数
Lyliane.name
Lyliane.HP
Lyliane.MP
Lyliane.statusDataDisplay()
は
ちゃんと生成されます
ですので
Lyliane.name = "リリアーネ";
Lyliane.HP = 10;
Lyliane.MP = 8;
Lyliane.statusDataDisplay();
を実行することができます
ここで再確認しておくと
今 私たちは
アクセス指定子
public
private
protected
を用いて
親クラスGameCharacterから
子クラスDragonへ
class Dragon:public GameCharacter
class Dragon:private GameCharacter
class Dragon:protected GameCharacter
のように
クラスの継承を行った場合
アクセス指定子が
💖public💖に設定された
親クラスGameCharacterのメンバ変数宣言
string name;
int HP;
int MP;
親クラスGameCharacterのメンバ関数宣言
void statusDataDisplay();
は
子クラスDragonのクラス宣言内に引き継がれるかどうか
を確認していますが
親クラスGameCharacterのメンバ変数宣言
string name;
int HP;
int MP;
親クラスGameCharacterのメンバ関数宣言
void statusDataDisplay();
は
アクセス指定子が
public
private
protected
に変更された状態で
つまり
public:
string name;
int HP;
int MP;
void statusDataDisplay();
private:
string name;
int HP;
int MP;
void statusDataDisplay();
protected:
string name;
int HP;
int MP;
void statusDataDisplay();
のように
子クラスDragonのクラス宣言内に
引き継がれる
記述される
ということまで確認できました
親クラスGameCharacterのメンバ変数宣言のアクセス指定子が
publicに設定されている場合
親クラスGameCharacterから
子クラスDragonへ
class Dragon:public GameCharacter
class Dragon:private GameCharacter
class Dragon:protected GameCharacter
のように
クラスの継承を行った場合
親クラスGameCharacterのメンバ変数宣言
string name;
int HP;
int MP;
親クラスGameCharacterのメンバ関数宣言
void statusDataDisplay();
は
アクセス指定子が
public
private
protected
に変更されるものの
💖必ず💖
子クラスDragonのクラス宣言内に引き継がれるのは分かりましたね
ここまでのお話を
💖前提とした状態で💖
さらに
アクセス指定子が
💖public💖に設定された
親クラスGameCharacterのメンバ変数宣言
string name;
int HP;
int MP;
親クラスGameCharacterのメンバ関数宣言
void statusDataDisplay();
が
class Dragon:public GameCharacter
class Dragon:private GameCharacter
class Dragon:protected GameCharacter
によって
クラスの継承を行った場合
アクセス指定子が
public
private
protected
に変更された状態で
つまり
public:
string name;
int HP;
int MP;
void statusDataDisplay();
private:
string name;
int HP;
int MP;
void statusDataDisplay();
protected:
string name;
int HP;
int MP;
void statusDataDisplay();
のように
子クラスDragonのクラス宣言内に引き継がれたとき
main関数内で
Pokkyの
Dragon Pokky;
を行って
子クラスDragon型のオブジェクトPokkyを作製したとき
子クラスDragon型のオブジェクトPokkyのメンバ変数
Pokky.name
Pokky.HP
Pokky.MP
子クラスDragon型のオブジェクトPokkyのメンバ関数
Pokky.statusDataDisplay()
は生成されるか?
使用できるか?
どうかを観察していくことになります
(もちろん 先のお話になりますが
親クラスGameCharacterから
子クラスDragonへ
class Dragon:public GameCharacter
class Dragon:private GameCharacter
class Dragon:protected GameCharacter
のように
クラスの継承を行った場合では
Pokkyの子クラスDragon型のオブジェクト宣言
Dragon Pokky;
を行って
子クラスDragon型のオブジェクトPokkyを作製したときに
子クラスDragon型のオブジェクトPokkyのメンバ変数
Pokky.name
Pokky.HP
Pokky.MP
子クラスDragon型のオブジェクトPokkyのメンバ関数
Pokky.statusDataDisplay()
が
生成される場合
と
生成されない場合が
出てきます)
ちょっとお話が脱線したかな?
何の話だったっけ・・・???
そうだ
親クラスGameCharacterのメンバ変数宣言
string name;
int HP;
int MP;
親クラスGameCharacterのメンバ関数宣言
void statusDataDisplay();
のアクセス指定子が
publicに設定された状態では
親クラスGameCharacterから
子クラスDragonへ
1.class Dragon:public GameCharacter
2.class Dragon:private GameCharacter
3.class Dragon:protected GameCharacter
のどのパターンで
クラスの継承をおこなっても
とりあえず
子クラスDragon内に
親クラスGameCharacterのメンバ変数宣言
string name;
int HP;
int MP;
親クラスGameCharacterのメンバ関数宣言
void statusDataDisplay();
は引き継がれることになるのです
こんな具合にです
👇
1.class Dragon:public GameCharacterの場合です
子クラスDragonのクラス宣言を観察してみましょう
👇
class Dragon :public GameCharacter {
public://👈🌞ここに注目
string name;
int HP;
int MP;
void statusDataDisplay();
public:
void useFireRecovery(GameCharacter& a);
};
2.class Dragon:private GameCharacterの場合です
👇
class Dragon :private GameCharacter {
private://👈🌞ここに注目
string name;
int HP;
int MP;
void statusDataDisplay();
public:
void useFireRecovery(GameCharacter& a);
};
3.class Dragon:protected GameCharacterの場合です
👇
class Dragon:protected GameCharacter {
protected://👈🌞ここに注目
string name;
int HP;
int MP;
void statusDataDisplay();
public:
void useFireRecovery(GameCharacter& a);
};
マックス「これが
基本の中の基本
ってわけなんだな😊」
ソーラー「そうなんです
そして
それとは全く関係なく
🌞Lylianeの親クラスGameCharacter型のオブジェクト宣言🌞
GameCharacter Lyliane;
を実行した場合
親クラスGameCharacterのメンバ変数
name
HP
MP
が用いられた
親クラスGameCharacter型のオブジェクトLylianeのメンバ変数
Lyliane.name
Lyliane.HP
Lyliane.MP
親クラスGameCharacter型のオブジェクトLylianeのメンバ関数
statusDataDisplay()
がもちいられた
親クラスGameCharacter型のオブジェクトLylianeのメンバ関数
Lyliane.statusDataDisplay()
は生成され、使用できることになります。」
マックス「
親クラスGameCharacterと子クラスDragonは別のクラスで
親クラスGameCharacterから子クラスDragonへ
クラスの継承が行われたからと言って
親クラスGameCharacterのクラス宣言に何か変化がおこるわけではないからなあ
🌞Lylianeの親クラスGameCharacter型のオブジェクト宣言🌞
が実行されているから
そうなるか」
ソーラー「そうなんです
ビルドエラーが生じることはありません
この
親クラスGameCharacterのメンバ変数宣言
string name;
int HP;
int MP;
親クラスGameCharacterのメンバ関数宣言
void statusDataDisplay();
のアクセス指定子が
publicに設定された状態では
親クラスGameCharacterから
子クラスDragonへ
class Dragon:public GameCharacter
class Dragon:private GameCharacter
class Dragon:protected GameCharacter
のどのパターンで
クラスの継承をおこなっても
親クラスGameCharacterのメンバ変数宣言
string name;
int HP;
int MP;
親クラスGameCharacterのメンバ関数宣言
void statusDataDisplay();
は
アクセス指定子が変更されるとはいえ
必ず
子クラスDragonのクラス宣言内に引き継がれるので
子クラスDragonのメンバ関数内で
引き継いでいないクラスGameCharacterのメンバ変数が使用されているといったような
ビルドエラーが生じることはないし
そもそも
親クラスGameCharacterのメンバ変数宣言
string name;
int HP;
int MP;
親クラスGameCharacterのメンバ関数宣言
void statusDataDisplay();
のアクセス指定子が
publicに設定された状態では
親クラスGameCharacter型のオブジェクト宣言
GameCharacter Lyliane;
を実行した場合
親クラスGameCharacterのメンバ変数
name
HP
MP
が用いられた
親クラスGameCharacter型のオブジェクトLylianeのメンバ変数
Lyliane.name
Lyliane.HP
Lyliane.MP
親クラスGameCharacterのメンバ関数
statusDataDisplay()
がもちいられた
親クラスGameCharacter型のオブジェクトLylianeのメンバ関数
Lyliane.statusDataDisplay()
が生成され
使用することができるというのは
当然の
大前提ですね
GameCharacter Lyliane;
Lyliane.name = "リリアーネ";
Lyliane.HP = 10;
Lyliane.MP = 8;
Lyliane.statusDataDisplay();
を実行してもビルドエラーが表示されるようなことはありません」
ソーラー「では
いよいよ
親クラスGameCharacterのメンバ変数宣言
string name;
int HP;
int MP;
親クラスGameCharacterのメンバ関数宣言
void statusDataDisplay();
のアクセス指定子がpublicに設定された状態で
class Dragon:
class Dragon:
class Dragon:
のように
アクセス指定子
public
protected
protected
を用いて
親クラスGameCharacterから
子クラスDragonへ
クラスの継承を行った状態で
🥒Pokkyの子クラスDragon型のオブジェクト宣言🥒
🍋Dragon Pokky;🍋
を
実行してみます。
子クラスDragon内には
次のように
親クラスGameCharacterのメンバ変数宣言
string name;
int HP;
int MP;
親クラスGameCharacterのメンバ関数宣言
void statusDataDisplay();
が記述されていることになります
👇
class Dragon:public GameCharacter {
public:
string name;
int HP;
int MP;
void statusDataDisplay();
public:
void useFireRecovery(GameCharacter& a);
👇
class Dragon:private GameCharacter {
private:
string name;
int HP;
int MP;
void statusDataDisplay();
public:
void useFireRecovery(GameCharacter& a);
👇
class Dragon:protected GameCharacter {
protected:
string name;
int HP;
int MP;
void statusDataDisplay();
public:
void useFireRecovery(GameCharacter& a);
};
ここでの
ポイントは
Pokkyの
Dragon Pokky;
が実行されるということです
こうなってくると
親クラスGameCharacterから
子クラスDragonへ
class Dragon:public GameCharacter
class Dragon:private GameCharacter
class Dragon:protected GameCharacter
のどのパターンで
継承
がおこなわれるかが関係してくることになります。
子クラスDragonのクラス宣言は
1.class Dragon:public GameCharacterの場合です
👇
class Dragon :public GameCharacter {
public://👈🌞ここに注目
string name;
int HP;
int MP;
void statusDataDisplay();
public:
void useFireRecovery(GameCharacter& a);
};
2.class Dragon:private GameCharacterの場合です
👇
class Dragon :private GameCharacter {
private://👈🌞ここに注目
string name;
int HP;
int MP;
void statusDataDisplay();
public:
void useFireRecovery(GameCharacter& a);
};
3.class Dragon:protected GameCharacterの場合です
👇
class Dragon:protected GameCharacter {
protected://👈🌞ここに注目
string name;
int HP;
int MP;
void statusDataDisplay();
public:
void useFireRecovery(GameCharacter& a);
};
と記述されていることになりますからね
いままでのエピソードで
class Dragon:public GameCharacter
class Dragon:private GameCharacter
の場合は検証してきたので
今度は
class Dragon:protected GameCharacter
の場合を検証してみたいと思います
そのプログラムはこちらとなります。」
👇
#include <iostream>
#include <string>//文字列を取り扱うためにヘッダファイル <string>をインクルードしています
using namespace std;
//👇🌞🌞🌞クラスGameCharacterです🌞🌞🌞
class GameCharacter {
public:
string name;
int HP;
int MP;
void statusDataDisplay();
//クラスGameCharacterにはuseFireRecovery(GameCharacter& a)を設定しません
};
void GameCharacter::statusDataDisplay() {
cout << name << "\n";
cout << "HP " << HP << "\n";
cout << "MP " << MP << "\n";
}
//👇🌞🌞🌞クラスGameCharacterを継承したクラスDragonです🌞🌞🌞
//👇🌞🌞🌞protectedを用いて継承がおこなわれています🌞🌞🌞
class Dragon:protected GameCharacter {
public:
void useFireRecovery(GameCharacter& a);
};
void Dragon::useFireRecovery(GameCharacter& a) {
cout << name << "は灼熱のフレアを" << a.name << "に吐いた !" << "\n";
cout << a.name << "は灼熱のフレアを受け燃え上がった!" << "\n";
a.HP += 10;
cout << a.name << "の体力は10回復した" << "\n";
}
int main() {
Dragon Pokky;
Pokky.name = "ポッキー";
Pokky.HP = 15;
Pokky.MP = 5;
Pokky.statusDataDisplay();
return 0;
}
ビルド実行結果
重大度レベル コード 説明 プロジェクト ファイル 行 抑制状態
エラー (アクティブ) E0265 関数 "GameCharacter::statusDataDisplay" (宣言された 行 19) にアクセスできません
エラー (アクティブ) E0265 メンバー "GameCharacter::name" (宣言された 行 9) にアクセスできません
エラー (アクティブ) E0265 メンバー "GameCharacter::MP" (宣言された 行 11) にアクセスできません
エラー (アクティブ) E0265 メンバー "GameCharacter::HP" (宣言された 行 10) にアクセスできません
エラー C2247 'GameCharacter::statusDataDisplay' はアクセスできません。'Dragon' は 'protected' で 'GameCharacter' からの継承で使われています。
エラー C2247 'GameCharacter::name' はアクセスできません。'Dragon' は 'protected' で 'GameCharacter' からの継承で使われています。
エラー C2247 'GameCharacter::MP' はアクセスできません。'Dragon' は 'protected' で 'GameCharacter' からの継承で使われています。
エラー C2247 'GameCharacter::HP' はアクセスできません。'Dragon' は 'protected' で 'GameCharacter' からの継承で使われています。
マックス「なんだ
ビルド実行できていないか・・・
原因はどこなんだ・・・??
親クラスGameCharacterのメンバ変数宣言
string name;
int HP;
int MP;
親クラスGameCharacterのメンバ関数宣言
void statusDataDisplay();
のアクセス指定子がpublicに設定された状態で
class Dragon:protected GameCharacter
のように
親クラスGameCharacterから
子クラスDragonへ
アクセス指定子protectedを使って
クラスの継承を行った場合でも
親クラスGameCharacterのメンバ変数宣言
string name;
int HP;
int MP;
親クラスGameCharacterのメンバ関数宣言
void statusDataDisplay();
は
アクセス指定子がprotectedに変更されているとはいえ
子クラスDragonのクラス宣言内に
引き継がれている
だから
子クラスDragonのメンバ関数useFireRecovery(GameCharacter& a)内で
引き継いでいないクラスGameCharacterのメンバ変数
name
HP
MP
が使用されているといったようなことが
ビルドエラーとして表示されているわけではない・・・
子クラスDragon内には
親クラスGameCharacterのメンバ変数宣言
string name;
int HP;
int MP;
親クラスGameCharacterのメンバ関数宣言
void statusDataDisplay();
のアクセス指定子がprotectedの状態で以下のように記述されていることになるんだろう
👇
class Dragon:protected GameCharacter {
protected:
string name;
int HP;
int MP;
void statusDataDisplay();
public:
void useFireRecovery(GameCharacter& a);
};
となると・・・
単純に
この
子クラスDragonをみれば一目瞭然だな《😊😊😊😊😊😊😊😊😊😊😊😊😊😊😊😊😊》
Pokkyの
Dragon Pokky;
を実行して
Dragon型のオブジェクトPokkyを作製しても
親クラスGameCharacterのメンバ変数
name
HP
MP
が用いられた
子クラスDragon型のオブジェクトPokkyのメンバ変数
Pokky.name
Pokky.HP
Pokky.MP
親クラスGameCharacterのメンバ関数
statusDataDisplay()
が用いられた
子クラスDragon型のオブジェクトPokkyのメンバ関数
Pokky.statusDataDisplay()
は生成されないってことがわかる
なぜかというと
以前のエピソードでもみてきたように
クラスの継承の話ではなく
普通のクラスの
メンバ変数宣言、メンバ関数宣言に
protectedを設定した場合
protected
は
privateとして働く性質があるからだ
だから
今の子クラスDragonの
アクセス指定子
protectedの部分をprivateにおきかえてみるとわかりやすい
となると
Pokkyの子クラスDragon型のオブジェクト宣言
Dragon Pokky;
を実行しても
子クラスDragon型のオブジェクトPokkyのメンバ変数
Pokky.name
Pokky.HP
Pokky.MP
子クラスDragon型のオブジェクトPokkyのメンバ関数
Pokky.statusDataDisplay()
は生成されないことがわかる
子クラスDragon型のオブジェクトPokkyのメンバ変数
Pokky.name
Pokky.HP
Pokky.MP
子クラスDragon型のオブジェクトPokkyのメンバ関数
Pokky.statusDataDisplay()
が生成されていないのに
Dragon Pokky;
Pokky.name = "ポッキー";
Pokky.HP = 15;
Pokky.MP = 5;
Pokky.statusDataDisplay();
を実行しているから
ビルドエラーが表示されていることになるってわけだ
ここまでは見切ったあぁぁヽ(^。^)ノ
ううん・・・
となると・・・?
さっきのエピソードを見返してみると・・・
親クラスGameCharacterから
子クラスDragonへの
クラスの継承で
アクセス指定子privateを用いた
class Dragon:private GameCharacter
を
実行した場合
と
アクセス指定子protectedを用いた
class Dragon:protected GameCharacter
を
実行した場合では
同じようなビルドエラーが表示されているじゃないか
ともに
Pokkyの
Dragon Pokky;
を実行しても
親クラスGameCharacterのメンバ変数
name
HP
MP
が用いられた
子クラスDragon型のオブジェクトPokkyのメンバ変数
Pokky.name
Pokky.HP
Pokky.MP
親クラスGameCharacterのメンバ関数
statusDataDisplay()
が用いられた
子クラスDragon型のオブジェクトPokkyのメンバ関数
Pokky.statusDataDisplay()
を使用できなくなっている
じゃあ
アクセス指定子privateを用いた
class Dragon:private GameCharacter
でクラスの継承を行う場合と
アクセス指定子protectedを用いた
class Dragon:protected GameCharacter
でクラスの継承を行う場合では
違いはないってこと・・・か・・・?
」
てんC「
親クラスGameCharacterから
子クラスDragonへの
クラスの継承で
アクセス指定子privateを用いた場合
と
アクセス指定子protectedを用いた場合
では
2.class Dragon:private GameCharacterの場合
class Dragon :private GameCharacter {
private:
string name;
int HP;
int MP;
void statusDataDisplay();
public:
void useFireRecovery(GameCharacter& a);
};
3.class Dragon:protected GameCharacterの場合
class Dragon :protected GameCharacter {
protected:
string name;
int HP;
int MP;
void statusDataDisplay();
public:
void useFireRecovery(GameCharacter& a);
};
のように
子クラスDragonのクラス宣言内に
親クラスGameCharacterのメンバ変数宣言
string name;
int HP;
int MP;
親クラスGameCharacterのメンバ関数宣言
void statusDataDisplay();
は引き継がれているのですね
private:
string name;
int HP;
int MP;
void statusDataDisplay();
public:
void useFireRecovery(GameCharacter& a);
と
protected:
string name;
int HP;
int MP;
void statusDataDisplay();
public:
void useFireRecovery(GameCharacter& a);
ではどのような違いがでてくるのか
ですか・・・?
この場合
protected:
string name;
int HP;
int MP;
void statusDataDisplay();
の
protected
は
private
と
おなじ働きをするので
2.class Dragon:private GameCharacterの場合
class Dragon :private GameCharacter {
private:
string name;
int HP;
int MP;
void statusDataDisplay();
public:
void useFireRecovery(GameCharacter& a);
};
と
3.class Dragon:protected GameCharacterの場合
class Dragon :protected GameCharacter {
protected:
string name;
int HP;
int MP;
void statusDataDisplay();
public:
void useFireRecovery(GameCharacter& a);
};
のクラス宣言は
全く同じクラス宣言となり
違いはないということになります
ともに
Pokkyの
Dragon Pokky;
を実行しても
親クラスGameCharacterのメンバ変数
name
HP
MP
が用いられた
子クラスDragon型のオブジェクトPokkyのメンバ変数
Pokky.name
Pokky.HP
Pokky.MP
親クラスGameCharacterのメンバ関数
statusDataDisplay()
が用いられた
子クラスDragon型のオブジェクトPokkyのメンバ関数
Pokky.statusDataDisplay()
は
生成されず
使用することはできません」
ソーラー「そのとおりです(´▽`*)
繰り返すと
親クラスGameCharacter
の
メンバ変数宣言
string name;
int HP;
int MP;
メンバ関数宣言
void statusDataDisplay();
のアクセス指定子がpublic に設定された状態では
アクセス指定子privateを用いて
class Dragon:private GameCharacter
のように
クラスの継承を行った場合も
アクセス指定子protectedを用いて
class Dragon:protected GameCharacter
のように
クラスの継承を行った場合も
ちゃんと
子クラスDragonのクラス宣言内に
親クラスGameCharacter
の
メンバ変数宣言
string name;
int HP;
int MP;
メンバ関数宣言
void statusDataDisplay();
は引き継がれています
だからこそ
子クラスDragonのメンバ関数useFireRecovery(GameCharacter& a) の定義内で
👇
void Dragon::useFireRecovery(GameCharacter& a) {
cout << name << "は灼熱のフレアを" << a.name << "に吐いた !" << "\n";
cout << a.name << "は灼熱のフレアを受け燃え上がった!" << "\n";
a.HP += 10;
cout << a.name << "の体力は10回復した" << "\n";
}
👆
親クラスGameCharacterのメンバ変数
name
を使用することができているんです
つまり
子クラスDragonのクラス宣言内に
親クラスGameCharacter
の
メンバ変数宣言
string name;
が引き継がれていなければ
nameを
子クラスDragonのメンバ関数useFireRecovery(GameCharacter& a)の定義内では使用することはできない
というわけです😊
💖そのこととは別に💖
クラスの継承で
アクセス指定子privateを用いた場合と
アクセス指定子protectedを用いた場合では
Pokkyの
Dragon Pokky;
を実行して
Dragon型のオブジェクトPokkyを作製したとしても
親クラスGameCharacter
の
メンバ変数
name
HP
MP
がもちいられた
子クラスDragon型のオブジェクトPokkyのメンバ変数
Pokky.name
Pokky.HP
Pokky.MP
親クラスGameCharacterのメンバ関数
statusDataDisplay()
が用いられた
子クラスDragon型のオブジェクトPokkyのメンバ関数
Pokky.statusDataDisplay()
は生成されないので使用することはできなくなるんです」
マックス「
親クラスGameCharacter
の
メンバ変数宣言
string name;
int HP;
int MP;
メンバ関数宣言
void statusDataDisplay();
のアクセス指定子がpublic に設定された状態では
アクセス指定子privateを用いて
class Dragon:private GameCharacter
のように
クラスの継承を行った場合も
アクセス指定子protectedを用いて
class Dragon:protected GameCharacter
のように
クラスの継承を行った場合も
ちゃんと
子クラスDragonのクラス宣言内に
親クラスGameCharacter
の
メンバ変数宣言
string name;
int HP;
int MP;
メンバ関数宣言
void statusDataDisplay();
は引き継がれている
が
親クラスGameCharacter
の
メンバ変数
name
HP
MP
がもちいられた
子クラスDragon型のオブジェクトPokkyのメンバ変数
Pokky.name
Pokky.HP
Pokky.MP
親クラスGameCharacterのメンバ関数
statusDataDisplay()
が用いられた
子クラスDragon型のオブジェクトPokkyのメンバ関数
Pokky.statusDataDisplay()
は生成されないということはわかった
じゃあ
アクセス指定子privateを用いて
class Dragon:private GameCharacter
のように
クラスの継承を行った場合と
アクセス指定子protectedを用いて
class Dragon:protected GameCharacter
のように
クラスの継承を行った場合の意味とはなんなんだ?」
ソーラー「そうなるよね
そう
どちらの場合でも
Pokkyの
Dragon Pokky;
を実行したのち
親クラスGameCharacter
の
メンバ変数
name
HP
MP
が用いられた
子クラスDragon型のオブジェクトPokkyのメンバ変数
Pokky.name
Pokky.HP
Pokky.MP
は生成されないので
子クラスDragon型のオブジェクトPokkyのメンバ変数
Pokky.name
Pokky.HP
Pokky.MP
に
🍊直接🍊
Pokky.name = "ポッキー";
Pokky.HP = 15;
Pokky.MP = 5;
のように
データを代入することはできません。」
マックス「だいたい
Pokky.name = "ポッキー";
Pokky.HP = 15;
Pokky.MP = 5;
のように
データを代入できないんでは
アクセス指定子private
アクセス指定子protected
を用いて
親クラスGameCharacterから
子クラスDragonへ
class Dragon:private GameCharacter
class Dragon:protected GameCharacter
のように
クラスの継承を行っても
意味がなくなるんじゃないか?」
ソーラー「
そうですね。
アクセス指定子privateを用いて
class Dragon:private GameCharacter
のように
クラスの継承を行った場合と
アクセス指定子protectedを用いて
class Dragon:protected GameCharacter
のように
クラスの継承を行った場合は不便にみえます
それは
親クラスGameCharacterから子クラスDragonへ
アクセス指定子
public
を用いて
クラスの継承をおこなった場合は
Pokkyの
Dragon Pokky;
を実行したのち
親クラスGameCharacter
の
メンバ変数
name
HP
MP
が用いられた
子クラスDragon型のオブジェクトPokkyのメンバ変数
Pokky.name
Pokky.HP
Pokky.MP
が
ちゃんと生成されるので
子クラスDragon型のオブジェクトPokkyのメンバ変数
Pokky.name
Pokky.HP
Pokky.MP
に
🍊直接🍊
Pokky.name = "ポッキー";
Pokky.HP = 15;
Pokky.MP = 5;
のように
データを代入することはできます
それと違い
親クラスGameCharacterから子クラスDragonへ
アクセス指定子private
アクセス指定子protected
を用いて
クラスの継承をおこなった場合は
Pokkyの
Dragon Pokky;
を実行して
クラスDragon型のオブジェクトPokkyを作製した際
親クラスGameCharacter
の
メンバ変数
name
HP
MP
が用いられた
子クラスDragon型のオブジェクトPokkyのメンバ変数
Pokky.name
Pokky.HP
Pokky.MP
は生成されません
ですので
🌞直接🌞
子クラスDragon型のオブジェクトPokkyのメンバ変数
Pokky.name
Pokky.HP
Pokky.MP
を用いて
Pokky.name = "ポッキー";
Pokky.HP = 15;
Pokky.MP = 5;
のように
データを代入することはできません
しかし
🌞子クラスDragon型のオブジェクトのメンバ関数🌞
を用いて
🍋間接的🍋に
子クラスDragon型のオブジェクトPokkyのメンバ変数
Pokky.name
Pokky.HP
Pokky.MP
にデータを代入することができるんです
( まさにカプセル化の説明をソーラーはおこなっています
solarplexussより)
つまり
親クラスGameCharacter
の
メンバ変数宣言
string name;
int HP;
int MP;
メンバ関数宣言
void statusDataDisplay();
のアクセス指定子がpublic に設定された状態で
アクセス指定子privateを用いて
class Dragon:private GameCharacter
のように
クラスの継承を行った場合と
アクセス指定子protectedを用いて
class Dragon:protected GameCharacter
のように
クラスの継承を行った場合は
カプセル化
が行われることになるんです」
新規登録で充実の読書を
- マイページ
- 読書の状況から作品を自動で分類して簡単に管理できる
- 小説の未読話数がひと目でわかり前回の続きから読める
- フォローしたユーザーの活動を追える
- 通知
- 小説の更新や作者の新作の情報を受け取れる
- 閲覧履歴
- 以前読んだ小説が一覧で見つけやすい
アカウントをお持ちの方はログイン
ビューワー設定
文字サイズ
背景色
フォント
組み方向
機能をオンにすると、画面の下部をタップする度に自動的にスクロールして読み進められます。
応援すると応援コメントも書けます