親クラスのクラス宣言内でアクセス指定子が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


のように


アクセス指定子


protected


を用いて


親クラスGameCharacterから


子クラスDragonへ


クラスの継承を行ってみたいと思います


(結局はカプセル化がおこなわれることになるのですが・・・)


class Dragon:protected💖💖💖💖💖💖💖💖💖 GameCharacter


のように


アクセス指定子


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🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞型のオブジェクト宣言


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:public💖💖💖💖💖💖💖💖💖 GameCharacter

class Dragon:private💖💖💖💖💖💖💖💖💖 GameCharacter

class Dragon:protected💖💖💖💖💖💖💖💖💖 GameCharacter


のように


アクセス指定子

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💖💖💖💖💖💖型のオブジェクト宣言


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💖💖💖💖💖💖型のオブジェクト宣言


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💖💖💖💖💖💖型のオブジェクト宣言


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💖💖💖💖💖💖型のオブジェクト宣言


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💖💖💖💖💖💖型のオブジェクト宣言


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💖💖💖💖💖💖型のオブジェクト宣言


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💖💖💖💖💖💖型のオブジェクト宣言


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💖💖💖💖💖💖型のオブジェクト宣言


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

のように


クラスの継承を行った場合は




             カプセル化



が行われることになるんです」











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

作者を応援しよう!

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

応援したユーザー

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

新規登録で充実の読書を

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

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

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