親クラス*型のポインタ変数に子クラス型のオブジェクトのアドレスを入れ替えて代入することにより関数のポリモーフィズム(多態性)を実現させてみましょう

ソーラー「それでは


          純粋仮想関数



が用いられた


プログラムを実行していきたいと思います。」




ソーラー「まず一つの親クラスと


その親クラスのメンバ変数宣言、メンバ関数宣言を


継承した


子クラスを


3つ用意します


まずは


親クラスCharacterのクラス宣言と


親クラスCharacterのメンバ関数characterdisplay()


の定義を

             

👇

____________________________________


class Character{



public:

virtual void characterdisplay()=0;


};


//🌞virtual void characterdisplay()は純粋仮想関数なので定義を記述していません



____________________________________


とします


親クラスCharacterのメンバ関数characterdisplay()


は純粋仮想関数に設定されています


純粋仮想関数が設定されているので親クラスCharacterは抽象クラスです


そして


1つ目の


子クラスである


CircleCharacterのクラス宣言と


子クラスCircleCharacterのメンバ関数


characterdisplay()


の定義を

👇

          

_____________________________________________________________________

class CircleCharacter:public Character

{


public:


void characterdisplay();//自作関数void characterdisplay()はクラスCircleCharacterのメンバ関数とよばれます


};


void CircleCharacter::characterdisplay(){


cout << "〇" ;

}



____________________________________


とします。」



マックス「子クラスCircleCharacter(〇文字クラス)は




コマンドプロンプト画面に表示する機能を持っているクラスというわけか」


ソーラー「子クラスCircleCharacter型のオブジェクト宣言


CircleCharacter circle1;


を実行し


生成される


子クラスCircleCharacter型のオブジェクトcircle1のメンバ関数


circle1 characterdisplay();


を実行すると



親クラスCharacterのメンバ関数


characterdisplay()



(純粋)仮想関数であるないに関わらず



  オーバーライドの働きにより



親クラスCharacterのメンバ関数


characterdisplay()


の定義のかわりに


子クラスCircleCharacterのメンバ関数


characterdisplay()


の定義


void CircleCharacter::characterdisplay(){


cout << "〇" ;

}



が用いられたものが実行されることになります


cout << "〇" ;


が実行されるので


〇がコマンドプロンプト画面に表示されます。」



次に


2つ目の


子クラスである


StarCharacterのクラス宣言と


子クラスStarCharacterのメンバ関数


characterdisplay()


の定義を

👇

          

_____________________________________________________________________

class StarCharacter:public Character

{


public:


void characterdisplay();//自作関数void characterdisplay()はクラスStarCharacterのメンバ関数とよばれます


};


void StarCharacter::characterdisplay(){


cout << "☆" ;

}



____________________________________


とします。」





マックス「子クラスStarCharacter(☆文字クラス)は



をコマンドプロンプト画面に表示する機能を持っているクラスというわけか」


ソーラー「子クラスStarCharacter型のオブジェクト宣言


StarCharacter star1;


を実行し


生成される


子クラスStarCharacter型のオブジェクトstar1のメンバ関数


star1 characterdisplay();


を実行すると



親クラスCharacterのメンバ関数


characterdisplay()



(純粋)仮想関数であるないに関わらず



     オーバーライドの働きにより


親クラスCharacterのメンバ関数


void characterdisplay()


の定義のかわりに


子クラスStarCharacterのメンバ関数


characterdisplay()


の定義


void StarCharacter::characterdisplay(){


cout << "☆" ;

}



が用いられたものが実行されることになります


cout << "☆" ;


が実行されるので


☆がコマンドプロンプト画面に表示されます。」



ソーラー「


3つ目の


子クラスである


SquareCharacterのクラス宣言と


子クラスSquareCharacterのメンバ関数


void characterdisplay()


の定義を

👇

          

_____________________________________________________________________

class SquareCharacter:public Character

{


public:


void characterdisplay();//自作関数void characterdisplay()はクラスSquareCharacterのメンバ関数とよばれます


};


void SquareCharacter::characterdisplay(){


cout << "□" ;

}



____________________________________


とします。」





マックス「子クラスSquareCharacter(□クラス)は



をコマンドプロンプト画面に表示する機能を持っているクラスというわけか」


ソーラー「子クラスSquareCharacter型のオブジェクト宣言


SquareCharacter square1;


を実行し


生成される


子クラスSquareCharacter型のオブジェクトsquare1のメンバ関数


square1 characterdisplay();


を実行すると



親クラスCharacterのメンバ関数


characterdisplay()



(純粋)仮想関数であるないに関わらず


オーバーライドの働きにより



親クラスCharacterのメンバ関数


characterdisplay()


の定義のかわりに


子クラスSquareCharacterのメンバ関数


characterdisplay()


定義が用いられたものが実行されることになります


子クラスSquareCharacterのメンバ関数の定義は

👇

void SquareCharacter::characterdisplay(){


cout << "□" ;

}


👆

なので


cout << "□" ;


が実行され


□がコマンドプロンプト画面に表示されます。」


ソーラー「これらのクラスを用いて


〇〇〇□□□

□□□☆☆☆

☆☆☆〇〇〇


をコマンドプロンプト画面に表示してみます


そのプログラムはこちらとなります。

👇


#include <iostream>


using namespace std;



class Character {



public:

virtual void characterdisplay()= 0;


};


//🌞virtual void characterdisplay()は純粋仮想関数なので定義を記述していません




class CircleCharacter:public Character

{


public:


void characterdisplay();//自作関数void characterdisplay()はクラスCircleCharacterのメンバ関数とよばれます


};


void CircleCharacter::characterdisplay() {


cout << "〇";


}




class StarCharacter :public Character

{


public:


void characterdisplay();//自作関数void characterdisplay()はクラスStarCharacterのメンバ関数とよばれます


};


void StarCharacter::characterdisplay() {


cout << "☆";


}




class SquareCharacter:public Character

{


public:


void characterdisplay();//自作関数void characterdisplay()はクラスSquareCharacterのメンバ関数とよばれます


};


void SquareCharacter::characterdisplay() {


cout << "□";


}



int main() {



CircleCharacter circle;

StarCharacter star;

SquareCharacter square;



circle.characterdisplay();

circle.characterdisplay();

circle.characterdisplay();

star.characterdisplay();

star.characterdisplay();

star.characterdisplay();


cout << "\n";


star.characterdisplay();

star.characterdisplay();

star.characterdisplay();

square.characterdisplay();

square.characterdisplay();

square.characterdisplay();


cout << "\n";


square.characterdisplay();

square.characterdisplay();

square.characterdisplay();

circle.characterdisplay();

circle.characterdisplay();

circle.characterdisplay();


cout << "\n";


return 0;

}


プログラムの実行結果


〇〇〇☆☆☆

☆☆☆□□□

□□□〇〇〇



ソーラー「さて


ここで


プログラムの実行結果を


〇〇〇☆☆☆

☆☆☆□□□

□□□〇〇〇


から


☆の部分

〇の部分


を入れ替えて


☆☆☆〇〇〇

〇〇〇□□□

□□□☆☆☆

コマンドプロンプト画面に表示してみたいと思います。


そのプログラムはどのように記述したらよいでしょうか?」


マックス「プログラムの実行結果を


〇〇〇☆☆☆

☆☆☆□□□

□□□〇〇〇


から


☆☆☆〇〇〇

〇〇〇□□□

□□□☆☆☆


か・・・・・


むむう・・・


ソーラー「


原理的にはとても簡単です


circle.characterdisplay();


の部分と

star.characterdisplay();


の部分を


入れ替えるだけです」


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

👇

#include <iostream>


using namespace std;



class Character {



public:

virtual void characterdisplay() = 0;


};


//🌞virtual void characterdisplay()は純粋仮想関数なので定義を記述していません




class CircleCharacter :public Character

{


public:


void characterdisplay();//自作関数void characterdisplay()はクラスCircleCharacterのメンバ関数とよばれます


};


void CircleCharacter::characterdisplay() {


cout << "〇";


}




class StarCharacter :public Character

{


public:


void characterdisplay();//自作関数void characterdisplay()はクラスStarCharacterのメンバ関数とよばれます


};


void StarCharacter::characterdisplay() {


cout << "☆";


}




class SquareCharacter :public Character

{


public:


void characterdisplay();//自作関数void characterdisplay()はクラスSquareCharacterのメンバ関数とよばれます


};


void SquareCharacter::characterdisplay() {


cout << "□";


}





int main() {



CircleCharacter circle;

StarCharacter star;

SquareCharacter square;


star.characterdisplay();

star.characterdisplay();

star.characterdisplay();

circle.characterdisplay();

circle.characterdisplay();

circle.characterdisplay();


cout << "\n";


circle.characterdisplay();

circle.characterdisplay();

circle.characterdisplay();

square.characterdisplay();

square.characterdisplay();

square.characterdisplay();


cout << "\n";


square.characterdisplay();

square.characterdisplay();

square.characterdisplay();

star.characterdisplay();

star.characterdisplay();

star.characterdisplay();


cout << "\n";


return 0;

}


プログラムの実行結果


☆☆☆〇〇〇

〇〇〇□□□

□□□☆☆☆


マックス「なんだ 簡単ではないか」


ソーラー「


今行われたことを


ポリモーフィズム(多態性)を用いて


実行してみたいと思います


#include <iostream>


using namespace std;



class Character {



public:

virtual void characterdisplay()= 0;


};


//🌞virtual void characterdisplay()は純粋仮想関数なので定義を記述していません




class CircleCharacter:public Character

{


public:


void characterdisplay();//自作関数void characterdisplay()はクラスCircleCharacterのメンバ関数とよばれます


};


void CircleCharacter::characterdisplay() {


cout << "〇";


}




class StarCharacter :public Character

{


public:


void characterdisplay();//自作関数void characterdisplay()はクラスStarCharacterのメンバ関数とよばれます


};


void StarCharacter::characterdisplay() {


cout << "☆";


}




class SquareCharacter:public Character

{


public:


void characterdisplay();//自作関数void characterdisplay()はクラスSquareCharacterのメンバ関数とよばれます


};


void SquareCharacter::characterdisplay() {


cout << "□";


}



int main() {


CircleCharacter circle;

StarCharacter star;

SquareCharacter square;


Character* a[3];

/*🌞親クラスCharacter*型のポインタ変数

a[0]

a[1]

a[2]


を生成しています*/




a[0]=&circle;

a[1]=&star;

a[2]=&square;



a[0]->characterdisplay();

a[0]->characterdisplay();

a[0]->characterdisplay();

a[1]->characterdisplay();

a[1]->characterdisplay();

a[1]->characterdisplay();


cout << "\n";


a[1]->characterdisplay();

a[1]->characterdisplay();

a[1]->characterdisplay();

a[2]->characterdisplay();

a[2]->characterdisplay();

a[2]->characterdisplay();


cout << "\n";


a[2]->characterdisplay();

a[2]->characterdisplay();

a[2]->characterdisplay();

a[1]->characterdisplay();

a[1]->characterdisplay();

a[1]->characterdisplay();


cout << "\n";


return 0;

}


プログラムの実行結果


〇〇〇☆☆☆

☆☆☆□□□

□□□〇〇〇


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


circleの子クラスCircleCharacter型のオブジェクト宣言


CircleCharacter circle;


starの子クラスStarCharacter型のオブジェクト宣言


StarCharacter star;


squareの子クラスSquareCharacter型のオブジェクト宣言


SquareCharacter square;


を実行して


子クラスCircleCharacter型のオブジェクトcircle

子クラスStarCharacter型のオブジェクトstar

子クラスSquareCharacter型のオブジェクトsquare


を生成しています


そのアドレス


a[0]=&circle;

a[1]=&star;

a[2]=&square;


Character*型のポインタ変数の配列宣言


Character* a[3];


により生成される配列変数


a[0]

a[1]

a[2]


a[0]=&circle;

a[1]=&star;

a[2]=&square;



代入しています

ですので


a[0]->characterdisplay();

a[1]->characterdisplay();

a[2]->characterdisplay();


が実行されると


親クラスCharacterのメンバ関数characterdisplay()が純粋仮想関数に設定されていて


           かつ


親クラスCharacterのメンバ関数characterdisplay()が



子クラスCircleCharacterのメンバ関数characterdisplay()

子クラスStarCharacterのメンバ関数characterdisplay()

子クラスSquareCharacterのメンバ関数characterdisplay()


によって


         オーバーライド


されているので



a[0]->

a[1]->

a[2]->


親クラスCharacterのメンバ関数characterdisplay()の定義にアクセスせず


a[0]->は

子クラスCircleCharacterのメンバ関数characterdisplay()の定義に


a[1]->は

子クラスStarCharacterのメンバ関数characterdisplay()の定義に


a[2]->は

子クラスSquareCharacterのメンバ関数characterdisplay()の定義に


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


ですので


a[0]->characterdisplay();

a[1]->characterdisplay();

a[2]->characterdisplay();


が実行されると



子クラスCircleCharacterのメンバ関数characterdisplay()の定義

👇

void CircleCharacter::characterdisplay() {


cout << "〇";


}

子クラスStarCharacterのメンバ関数characterdisplay()の定義

👇

void StarCharacter::characterdisplay() {


cout << "☆";


}


子クラスSquareCharacterのメンバ関数characterdisplay()の定義


void SquareCharacter::characterdisplay() {


cout << "□";


}


cout << "〇";

cout << "☆";

cout << "□";


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



ですので


a[0]->characterdisplay();

a[0]->characterdisplay();

a[0]->characterdisplay();

a[1]->characterdisplay();

a[1]->characterdisplay();

a[1]->characterdisplay();


cout << "\n";


a[1]->characterdisplay();

a[1]->characterdisplay();

a[1]->characterdisplay();

a[2]->characterdisplay();

a[2]->characterdisplay();

a[2]->characterdisplay();


cout << "\n";


a[2]->characterdisplay();

a[2]->characterdisplay();

a[2]->characterdisplay();

a[1]->characterdisplay();

a[1]->characterdisplay();

a[1]->characterdisplay();


cout << "\n";


が実行されると


プログラムの実行結果


〇〇〇☆☆☆

☆☆☆□□□

□□□〇〇〇


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


この


プログラムの実行結果を


〇〇〇☆☆☆

☆☆☆□□□

□□□〇〇〇


から


☆の部分

〇の部分


を入れ替えて


☆☆☆〇〇〇

〇〇〇□□□

□□□☆☆☆



コマンドプロンプト画面に表示してみたいと思います。



その場合は


a[0] = &circle;

a[1] = &star;

a[2] = &square;


とアドレスが


代入されている状態を


a[0] = &star;

a[1] =&circle;

a[2] = &square;


に変更すればいいだけなんです


すごいね(^_-)-☆」


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

👇


#include <iostream>


using namespace std;



class Character {



public:

virtual void characterdisplay() = 0;


};


//🌞virtual void characterdisplay()は純粋仮想関数なので定義を記述していません




class CircleCharacter :public Character

{


public:


void characterdisplay();//自作関数void characterdisplay()はクラスCircleCharacterのメンバ関数とよばれます


};


void CircleCharacter::characterdisplay() {


cout << "〇";


}




class StarCharacter :public Character

{


public:


void characterdisplay();//自作関数void characterdisplay()はクラスStarCharacterのメンバ関数とよばれます


};


void StarCharacter::characterdisplay() {


cout << "☆";


}




class SquareCharacter :public Character

{


public:


void characterdisplay();//自作関数void characterdisplay()はクラスSquareCharacterのメンバ関数とよばれます


};


void SquareCharacter::characterdisplay() {


cout << "□";


}



int main() {


Character* a[3];


CircleCharacter circle;

StarCharacter star;

SquareCharacter square;



a[0] = &circle;

a[1] = &star;

a[2] = &square;



a[0]->characterdisplay();

a[0]->characterdisplay();

a[0]->characterdisplay();

a[1]->characterdisplay();

a[1]->characterdisplay();

a[1]->characterdisplay();


cout << "\n";


a[1]->characterdisplay();

a[1]->characterdisplay();

a[1]->characterdisplay();

a[2]->characterdisplay();

a[2]->characterdisplay();

a[2]->characterdisplay();


cout << "\n";


a[2]->characterdisplay();

a[2]->characterdisplay();

a[2]->characterdisplay();

a[1]->characterdisplay();

a[1]->characterdisplay();

a[1]->characterdisplay();


cout << "\n";


a[0] = &star;//👈🌞ここがポイントです

a[1] = &circle; //👈🌞ここがポイントです

a[2] = &square; //👈🌞ここがポイントです


a[0]->characterdisplay();

a[0]->characterdisplay();

a[0]->characterdisplay();

a[1]->characterdisplay();

a[1]->characterdisplay();

a[1]->characterdisplay();


cout << "\n";


a[1]->characterdisplay();

a[1]->characterdisplay();

a[1]->characterdisplay();

a[2]->characterdisplay();

a[2]->characterdisplay();

a[2]->characterdisplay();


cout << "\n";


a[2]->characterdisplay();

a[2]->characterdisplay();

a[2]->characterdisplay();

a[1]->characterdisplay();

a[1]->characterdisplay();

a[1]->characterdisplay();


cout << "\n";



return 0;

}


プログラムの実行結果


〇〇〇☆☆☆

☆☆☆□□□

□□□〇〇〇

☆☆☆〇〇〇

〇〇〇□□□

□□□☆☆☆


マックス「おお・・・


なんかすごくないか・・・」


ソーラー「このプログラムのすごいところは


親クラスCharacter*のポインタ変数

a[0]

a[1]

a[2]

に代入されるアドレスを変更することにより


a[0]->characterdisplay();

a[1]->characterdisplay();

a[2]->characterdisplay();


には手を加えることなく


別の命令文、関数を実行できるということなんです


このことを


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


といいます



            🌞さらに さらに🌞



a[0]->characterdisplay();

a[0]->characterdisplay();

a[0]->characterdisplay();

a[1]->characterdisplay();

a[1]->characterdisplay();

a[1]->characterdisplay();


cout << "\n";


a[1]->characterdisplay();

a[1]->characterdisplay();

a[1]->characterdisplay();

a[2]->characterdisplay();

a[2]->characterdisplay();

a[2]->characterdisplay();


cout << "\n";


a[2]->characterdisplay();

a[2]->characterdisplay();

a[2]->characterdisplay();

a[1]->characterdisplay();

a[1]->characterdisplay();

a[1]->characterdisplay();


cout << "\n";


全体を


           🌞1つの関数とととらえると🌞



a[0]->characterdisplay();

a[0]->characterdisplay();

a[0]->characterdisplay();

a[1]->characterdisplay();

a[1]->characterdisplay();

a[1]->characterdisplay();


cout << "\n";


a[1]->characterdisplay();

a[1]->characterdisplay();

a[1]->characterdisplay();

a[2]->characterdisplay();

a[2]->characterdisplay();

a[2]->characterdisplay();


cout << "\n";


a[2]->characterdisplay();

a[2]->characterdisplay();

a[2]->characterdisplay();

a[1]->characterdisplay();

a[1]->characterdisplay();

a[1]->characterdisplay();


cout << "\n";



の部分には

全く変更を


くわえることなく


Character*型のポインタ変数の配列宣言


Character* a[3];


により生成される配列変数


a[0]

a[1]

a[2]


に代入されるアドレスを変更するだけで


ことなる関数を実行できていますね



  a[0]->characterdisplay();

a[0]->characterdisplay();

a[0]->characterdisplay();

a[1]->characterdisplay();

a[1]->characterdisplay();

a[1]->characterdisplay();


cout << "\n";


a[1]->characterdisplay();

a[1]->characterdisplay();

a[1]->characterdisplay();

a[2]->characterdisplay();

a[2]->characterdisplay();

a[2]->characterdisplay();


cout << "\n";


a[2]->characterdisplay();

a[2]->characterdisplay();

a[2]->characterdisplay();

a[1]->characterdisplay();

a[1]->characterdisplay();

a[1]->characterdisplay();


cout << "\n";    


全体を関数としてみた場合も


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


を備えることができるというわけなんだね」





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

作者を応援しよう!

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

応援したユーザー

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

新規登録で充実の読書を

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

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

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