クラスの継承を行う際に継承される側のクラスを仮想クラスに設定することができます。

ソーラー「ところで



次のような3つのクラスが用意されているとします。


まず


1つ目のクラスは


ロボットの胴体につけられたナンバー

ロボットの胴体の縦の長さ

ロボットの胴体の横の長さ

ロボットの胴体の高さの長さ


取り扱い


表示する機能をもつ


クラスRobotbodyです。


クラスRobotbodyのクラス宣言と


そのメンバ関数の定義は


👇

class Robotbody{


public:

int no; //変数noはクラスRobotbodyのメンバ変数とよばれます

public:

float tate; //変数tateはクラスRobotbodyのメンバ変数とよばれます

public:

float yoko; //変数yokoはクラスRobotbodyのメンバ変数とよばれます

public:

float takasa; //変数takasaはクラスRobotbodyのメンバ変数とよばれます



public:

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


};



void Robotbody::bodydatadisplay() {


cout << "ロボットの胴体につけられたナンバーは" << no << "です" << "\n";

cout << "ロボットの胴体の縦の長さは" << tate << "メートルです" << "\n";

cout << "ロボットの胴体の横の長さは" << yoko << "メートルです" << "\n";

cout << "ロボットの胴体の高さの長さは" << takasa << "メートルです" << "\n";

}

//クラスRobotbodyのメンバ関数となっている自作関数bodydatadisplay()の定義をおこなっています


👆


とします。


マックス「なんか、どっかでみたようなクラスだな?」


ソーラー「そ、そ~ですか?」


マックス「さっきのエピソードで登場したクラスじゃないか?


まあ


クラスRobotbodyを用いれば


ロボットの胴体のスペックデータを


取り扱い表示することができるというわけだ」



ソーラー「次に登場する2つ目のクラスは


ロボットの胴体につけられたナンバー

ロボットの胴体の縦の長さ

ロボットの胴体の横の長さ

ロボットの胴体の高さの長さ


取り扱い


表示する機能をもつ


クラスType1Robot1です。


クラスType1Robot1のクラス宣言と


そのメンバ関数の定義は


👇

class Type1Robot1 {


public:

int no1; //変数no1はクラスType1Robot1のメンバ変数とよばれます

public:

float tate1; //変数tate1はクラスType1Robot1のメンバ変数とよばれます

public:

float yoko1; //変数yoko1はクラスType1Robot1のメンバ変数とよばれます

public:

float takasa1; //変数takasa1はクラスType1Robot1のメンバ変数とよばれます



public:

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


};



void Type1Robot1::bodydatadisplay1(){


cout << "ロボットの胴体につけられたナンバーは" << no1<< "ですよ" << "\n";

cout << "ロボットの胴体の縦の長さは" << tate1<< "メートルですよ" << "\n";

cout << "ロボットの胴体の横の長さは" << yoko1 << "メートルですよ" << "\n";

cout << "ロボットの胴体の高さの長さは" << takasa1 << "メートルですよ" << "\n";

}

//クラスType1Robot1のメンバ関数となっている自作関数bodydatadisplay1()の定義をおこなっています



マックス「なんだ?


クラスType1Robot1?



クラスType1Robot1には


no1

tate1

yoko1

takasa1

void bodydatadisplay1()

とか

1がいろいろくっついているな( ^ω^)・・・


結局



クラスRobotbody

クラスType1Robot1


は両方とも



ロボットの胴体につけられたナンバー

ロボットの胴体の縦の長さ

ロボットの胴体の横の長さ

ロボットの胴体の高さの長さ



取り扱い


表示する機能を持つクラスなんだろう?


クラスRobotbody

クラスType1Robot1


では何が違うんだ?」



ソーラー「よ~く


クラスType1Robot1


のメンバ関数


          bodydatadisplay1()


のメンバ関数の定義


void Type1Robot1::bodydatadisplay1(){


cout << "ロボットの胴体につけられたナンバーは" << no1<< "ですよ" << "\n";

cout << "ロボットの胴体の縦の長さは" << tate1<< "メートルですよ" << "\n";

cout << "ロボットの胴体の横の長さは" << yoko1 << "メートルですよ" << "\n";

cout << "ロボットの胴体の高さの長さは" << takasa1 << "メートルですよ" << "\n";

}

//クラスType1Robot1のメンバ関数となっている自作関数bodydatadisplay1()の定義をおこなっています



をみてよ



クラスRobotbodyのメンバ関数


bodydatadisplay()


の定義は


void Robotbody::bodydatadisplay() {


cout << "ロボットの胴体につけられたナンバーは" << no << "です" << "\n";

cout << "ロボットの胴体の縦の長さは" << tate << "メートルです" << "\n";

cout << "ロボットの胴体の横の長さは" << yoko << "メートルです" << "\n";

cout << "ロボットの胴体の高さの長さは" << takasa << "メートルです" << "\n";

}

//クラスRobotbodのメンバ関数となっている自作関数bodydatadisplay()の定義をおこなっています



クラスType1Robot1


のメンバ関数


          bodydatadisplay1()


のメンバ関数の定義は


void Type1Robot1::bodydatadisplay1(){


cout << "ロボットの胴体につけられたナンバーは" << no1<< "ですよ" << "\n";

cout << "ロボットの胴体の縦の長さは" << tate1<< "メートルですよ" << "\n";

cout << "ロボットの胴体の横の長さは" << yoko1 << "メートルですよ" << "\n";

cout << "ロボットの胴体の高さの長さは" << takasa1 << "メートルですよ" << "\n";

}

//クラスType1Robot1のメンバ関数となっている自作関数bodydatadisplay1()の定義をおこなっています


となっています。


その違いが判るかな~?」


マックス「


クラスRobotbody


のメンバ関数bodydatadisplay()の定義の文末は


        


            『 です 』





クラスType1Robot1


のメンバ関数


          bodydatadisplay1()


の定義の文末は





            『 ですよ 』




になっている!


微妙な違いだな」


ソーラー「そうなんですよ。


次に登場する3つ目のクラスは


ロボットの胴体につけられたナンバー

ロボットの胴体の縦の長さ

ロボットの胴体の横の長さ

ロボットの胴体の高さの長さ


取り扱い

表示する機能をもつ


クラスType1Robot2です。


クラスType1Robot2のクラス宣言と


そのメンバ関数の定義は


👇

class Type1Robot2 {


public:

int no2; //変数no2はクラスType1Robot2 のメンバ変数とよばれます

public:

float tate2; //変数tate2はクラスType1Robot2 のメンバ変数とよばれます

public:

float yoko2; //変数yoko2はクラスType1Robot2 のメンバ変数とよばれます

public:

float takasa2; //変数takasa2はクラスType1Robot2 のメンバ変数とよばれます



public:

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


};



void Type1Robot2::bodydatadisplay2(){


cout << "ロボットの胴体につけられたナンバーは" << no2 << "ですよ~~~ん" << "\n";

cout << "ロボットの胴体の縦の長さは" << tate2<< "メートルですよ~~~ん" << "\n";

cout << "ロボットの胴体の横の長さは" << yoko2 << "メートルですよ~~~ん" << "\n";

cout << "ロボットの胴体の高さの長さは" << takasa2 << "メートルですよ~~~ん" << "\n";

}

//クラスType1Robot2のメンバ関数となっている自作関数bodydatadisplay2()の定義をおこなっています


マックス「今度も


ロボットの胴体につけられたナンバー

ロボットの胴体の縦の長さ

ロボットの胴体の横の長さ

ロボットの胴体の高さの長さ


取り扱い

表示する機能をもつ


クラスType1Robot2か・・・


クラスType1Robot2のメンバ関数


bodydatadisplay2()の定義


は文末が



           『ですよ~~~ん』


になっているな」


ソーラー「そうなんですよ~~~ん」


てんC「ですよ~~~ん」


ぶーにゃん「びくっ」


マックス「そういや


前のエピソードで登場した


クラスType1Robot(無印です(*^。^*)のメンバ関数


bodydatadisplay()の定義は文末が




            『 です 』



だったよな・・・


クラスType1Robotのメンバ関数bodydatadisplay()

クラスType1Robot1のメンバ関数bodydatadisplay1()

クラスType1Robot2のメンバ関数bodydatadisplay2()


か・・・


クラスType1Robot

クラスType1Robot

クラスType1Robot


は全部


ロボットの胴体につけられたナンバー

ロボットの胴体の縦の長さ

ロボットの胴体の横の長さ

ロボットの胴体の高さの長さ


を表示する機能をもっているんだが


クラスType1Robotのメンバ関数bodydatadisplay()

クラスType1Robot1のメンバ関数bodydatadisplay1()

クラスType1Robot2のメンバ関数bodydatadisplay2()



それぞれ


定義の文末が


『です』

『ですよ』

『ですよ~~~ん』


になっているというわけだ


Type1Robot1

Type1Robot2


全部クラスType1Robotに似たようなクラスだな


どんだけ


文末表示が異なるタイプの


ロボットの胴体につけられたナンバー

ロボットの胴体の縦の長さ

ロボットの胴体の横の長さ

ロボットの胴体の高さの長さ


取り扱い

表示する機能をもつ


クラスを用意しているんだ」


ソーラー「趣味です。


猫にかつおぶしときめています。


文末表現にはこだわりたいんです。」


ソーラー「さて


このエピソードで登場した


クラスRobotbody

クラスType1Robot1

クラスType1Robot2


👆

これらの3つのクラスを用いて




          🌞クラスの多重継承🌞




を行ってみたいと思います。




まずは


クラスRobotbody


Type1Robot1に継承してみたいと思います。」



マックス「なんで


ロボットの胴体につけられたナンバー

ロボットの胴体の縦の長さ

ロボットの胴体の横の長さ

ロボットの胴体の高さの長さ


取り扱い表示する機能をもつクラス


Robotbody



ロボットの胴体につけられたナンバー

ロボットの胴体の縦の長さ

ロボットの胴体の横の長さ

ロボットの胴体の高さの長さ


取り扱い表示する機能をもつクラス


Type1Robot1


に継承する必要があるんだ?」


ソーラー「それはですね。


ロボットの胴体につけられたナンバー

ロボットの胴体の縦の長さ

ロボットの胴体の横の長さ

ロボットの胴体の高さの長さ


を表示するにも


文末を


『です』


に表示したいときもあれば


『ですよ』


に表示したいときもあるよね😊


ですので


クラスRobotbody



クラスType1Robot1に


Type1Robot1:public Robotbody


のように継承して


クラスRobotbodyの


メンバ変数宣言

int no;

float tate;

float yoko;

float takasa;


メンバ関数宣言

void bodydatadisplay();


クラスType1Robot1


に引き継いでおけば


子クラス(派生クラス)となるType1Robot1を用いて


robotMIRAのType1Robot1型のオブジェクト宣言


Type1Robot1 robotMIRA;


を実行したとき


Type1Robot1型のオブジェクトrobotMIRAのメンバ変数


robotMIRA.no

robotMIRA.tate

robotMIRA.yoko

robotMIRA.takasa

robotMIRA.no1

robotMIRA.tate1

robotMIRA.yoko1

robotMIRA.takasa1



Type1Robot1型のオブジェクトrobotMIRAのメンバ関数


robotMIRA.bodydatadisplay//🌞👈ここね

robotMIRA.bodydatadisplay1()//🌞👈ここね


が生成されることになります。


文末表現を



      『 です 』


に表示したければ


robotMIRA.no=1;

robotMIRA.tate=1.0;

robotMIRA.yoko=1.0;

robotMIRA.takasa=1.0;

robotMIRA.bodydatadisplay();



実行して


ロボットの胴体につけられたナンバーは1です

ロボットの胴体の縦の長さは1メートルです

ロボットの胴体の横の長さは1メートルです

ロボットの胴体の高さの長さは1メートルです


を表示し


文末表現を



      『 ですよ 』


に表示したければ


robotMIRA.no1=1;

robotMIRA.tate1=1.0;

robotMIRA.yoko1=1.0;

robotMIRA.takasa1=1.0;

robotMIRA.bodydatadisplay1();



実行して


ロボットの胴体につけられたナンバーは1ですよ

ロボットの胴体の縦の長さは1メートルですよ

ロボットの胴体の横の長さは1メートルですよ

ロボットの胴体の高さの長さは1メートルですよ


を表示すればよいというわけです


その時のプログラムは


こちらです。


#include <iostream>


using namespace std;



class Robotbody{


public:

int no; //変数noはクラスRobotbodyのメンバ変数とよばれます

public:

float tate; //変数tateはクラスRobotbodyのメンバ変数とよばれます

public:

float yoko; //変数yokoはクラスRobotbodyのメンバ変数とよばれます

public:

float takasa; //変数takasaはクラスRobotbodyのメンバ変数とよばれます



public:

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


};



void Robotbody::bodydatadisplay() {


cout << "ロボットの胴体につけられたナンバーは" << no << "です" << "\n";

cout << "ロボットの胴体の縦の長さは" << tate << "メートルです" << "\n";

cout << "ロボットの胴体の横の長さは" << yoko << "メートルです" << "\n";

cout << "ロボットの胴体の高さの長さは" << takasa << "メートルです" << "\n";

}

//クラスRobotbodyのメンバ関数となっている自作関数bodydatadisplay()の定義をおこなっています




class Type1Robot1:public Robotbody{


public:

int no1; //変数no1はクラスType1Robot1のメンバ変数とよばれます

public:

float tate1; //変数tate1はクラスType1Robot1のメンバ変数とよばれます

public:

float yoko1; //変数yoko1はクラスType1Robot1のメンバ変数とよばれます

public:

float takasa1; //変数takasa1はクラスType1Robot1のメンバ変数とよばれます



public:

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


};



void Type1Robot1::bodydatadisplay1() {


cout << "ロボットの胴体につけられたナンバーは" << no1 << "ですよ" << "\n";

cout << "ロボットの胴体の縦の長さは" << tate1 << "メートルですよ" << "\n";

cout << "ロボットの胴体の横の長さは" << yoko1 << "メートルですよ" << "\n";

cout << "ロボットの胴体の高さの長さは" << takasa1 << "メートルですよ" << "\n";

}

//クラスType1Robot1のメンバ関数となっている自作関数bodydatadisplay1()の定義をおこなっています




int main() {



Type1Robot1 robotMIRA;


robotMIRA.no = 1;

robotMIRA.tate = 1.0;

robotMIRA.yoko = 1.0;

robotMIRA.takasa = 1.0;


robotMIRA.bodydatadisplay();



robotMIRA.no1 = 1;

robotMIRA.tate1 = 1.0;

robotMIRA.yoko1 = 1.0;

robotMIRA.takasa1 = 1.0;


robotMIRA.bodydatadisplay1();

return 0;

}


プログラムの実行結果


ロボットの胴体につけられたナンバーは1です

ロボットの胴体の縦の長さは1メートルです

ロボットの胴体の横の長さは1メートルです

ロボットの胴体の高さの長さは1メートルです

ロボットの胴体につけられたナンバーは1ですよ

ロボットの胴体の縦の長さは1メートルですよ

ロボットの胴体の横の長さは1メートルですよ

ロボットの胴体の高さの長さは1メートルですよ


マックス「う~むぅ


文末表現に


こだわりたい人はこだわるというわけか・・・」





ソーラー「今度は


クラスRobotbody



Type1Robot2に継承してみたいと思います。」



マックス「今度は


ロボットの胴体につけられたナンバー

ロボットの胴体の縦の長さ

ロボットの胴体の横の長さ

ロボットの胴体の高さの長さ


取り扱い

表示する機能をもつクラス


Robotbody



ロボットの胴体につけられたナンバー

ロボットの胴体の縦の長さ

ロボットの胴体の横の長さ

ロボットの胴体の高さの長さ


取り扱い

表示する機能をもつクラス


Type1Robot2


に継承するんか~~い」


ソーラー「それはですね。


ロボットの胴体につけられたナンバー

ロボットの胴体の縦の長さ

ロボットの胴体の横の長さ

ロボットの胴体の高さの長さ


を表示するにも


文末を


です


に表示したいときもあれば


ですよ~~~ん


に表示したいときもあるわけじゃないですか😊


ですので


クラスRobotbody


クラスType1Robot2に


Type1Robot2:public Robotbody


のように継承して


クラスRobotbodyの


メンバ変数宣言

int no;

float tate;

float yoko;

float takasa;


メンバ関数宣言

void bodydatadisplay();


クラスType1Robot2


に引き継いでおけば


子クラス(派生クラス)となるType1Robot2を用いて


robotMIRAのType1Robot2型のオブジェクト宣言


Type1Robot2 robotMIRA;


を実行したとき


Type1Robot2型のオブジェクトrobotMIRAのメンバ変数


robotMIRA.no

robotMIRA.tate

robotMIRA.yoko

robotMIRA.takasa

robotMIRA.no2

robotMIRA.tate2

robotMIRA.yoko2

robotMIRA.takasa2


Type1Robot2型のオブジェクトrobotMIRAのメンバ関数


robotMIRA.bodydatadisplay()//🌞👈ここね

robotMIRA.bodydatadisplay2()//🌞👈ここね


が生成されることになります。


文末表現を



      『 です 』



に表示したければ


robotMIRA.no=1;

robotMIRA.tate=1.0;

robotMIRA.yoko=1.0;

robotMIRA.takasa=1.0;

robotMIRA.bodydatadisplay();



実行すればいいですね


そして


文末表現を



      『 ですよ~~~ん 』



に表示したければ


robotMIRA.no2=1;

robotMIRA.tate2=1.0;

robotMIRA.yoko2=1.0;

robotMIRA.takasa2=1.0;

robotMIRA.bodydatadisplay2();



実行すればよいというわけです


その時のプログラムは


こちらです。


#include <iostream>


using namespace std;



class Robotbody{


public:

int no; //変数noはクラスRobotbodyのメンバ変数とよばれます

public:

float tate; //変数tateはクラスRobotbodyのメンバ変数とよばれます

public:

float yoko; //変数yokoはクラスRobotbodyのメンバ変数とよばれます

public:

float takasa; //変数takasaはクラスRobotbodyのメンバ変数とよばれます



public:

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


};



void Robotbody::bodydatadisplay() {


cout << "ロボットの胴体につけられたナンバーは" << no << "です" << "\n";

cout << "ロボットの胴体の縦の長さは" << tate << "メートルです" << "\n";

cout << "ロボットの胴体の横の長さは" << yoko << "メートルです" << "\n";

cout << "ロボットの胴体の高さの長さは" << takasa << "メートルです" << "\n";

}

//クラスRobotbodyのメンバ関数となっている自作関数bodydatadisplay()の定義をおこなっています




class Type1Robot2:public Robotbody{


public:

int no2; //変数no2はクラスType1Robot2のメンバ変数とよばれます

public:

float tate2; //変数tate1はクラスType1Robot2のメンバ変数とよばれます

public:

float yoko2; //変数yoko1はクラスType1Robot2のメンバ変数とよばれます

public:

float takasa2; //変数takasa2はクラスType1Robot2のメンバ変数とよばれます



public:

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


};



void Type1Robot2::bodydatadisplay2() {


cout << "ロボットの胴体につけられたナンバーは" << no2 << "ですよ~~~ん" << "\n";

cout << "ロボットの胴体の縦の長さは" << tate2 << "メートルですよ~~~ん" << "\n";

cout << "ロボットの胴体の横の長さは" << yoko2<< "メートルですよ~~~ん" << "\n";

cout << "ロボットの胴体の高さの長さは" << takasa2 << "メートルですよ~~~ん" << "\n";

}

//クラスType1Robot2のメンバ関数となっている自作関数bodydatadisplay2()の定義をおこなっています




int main() {



Type1Robot2 robotMIRA;


robotMIRA.no = 1;

robotMIRA.tate = 1.0;

robotMIRA.yoko = 1.0;

robotMIRA.takasa = 1.0;


robotMIRA.bodydatadisplay();



robotMIRA.no2 = 1;

robotMIRA.tate2 = 1.0;

robotMIRA.yoko2 = 1.0;

robotMIRA.takasa2 = 1.0;


robotMIRA.bodydatadisplay2();

return 0;

}


プログラムの実行結果


ロボットの胴体につけられたナンバーは1です

ロボットの胴体の縦の長さは1メートルです

ロボットの胴体の横の長さは1メートルです

ロボットの胴体の高さの長さは1メートルです

ロボットの胴体につけられたナンバーは1ですよ~~~ん

ロボットの胴体の縦の長さは1メートルですよ~~~ん

ロボットの胴体の横の長さは1メートルですよ~~~ん

ロボットの胴体の高さの長さは1メートルですよ~~~ん


マックス「なんかやってることは簡単だな


結局


クラスType1Robot1

クラスType1Robot2



それぞれ


クラスRobotbody



親クラス(基本クラス)として継承されているわけだ」


てんC「クラスRobotbodyは


大活躍ですね。」


マックス「めでたし、めでたし


というわけだな」



ソーラー「ここで はた と気付くんです。


文末表示を


『です』

『ですよ』


に表示できるよう


クラスRobotbody



クラスType1Robot1




文末表示を


『です』

『ですよ~~~ん』


に表示できるよう


クラスRobotbody



クラスType1Robot2



継承しました」


マックス「ふむふむ」


ソーラー「ですが


クラスType1Robot1


では


文末表示を


『です』

『ですよ』


だけに表示可能で


クラスType1Robot2


では


文末表示を


『です』

『ですよ~~~ん』


だけに表示可能


クラスType1Robot1

もしくは

クラスType1Robot2



どちらかだけでは



文末表示を


『です』

『ですよ』

『ですよ~~~ん』


に表示するよう


プログラムを実行することはできないですよね。」



マックス「そりゃあ そうじゃろう、そうじゃろう」


ソーラー「そこで


メンバ変数宣言

メンバ関数宣言


が設定されていない空っぽのクラス


クラスType1Robot1plus2


を新設して


クラスType1Robot1

クラスType1Robot2



新設したクラス


クラスType1Robot1plus2



継承すれば


クラスType1Robot1



メンバ変数宣言

int no;

float tate;

float yoko;

float takasa;

int no1;

float tate1;

float yoko1;

float takasa1;


メンバ関数宣言

void bodydatadisplay();

void bodydatadisplay1();



クラスType1Robot2



メンバ変数宣言

int no;

float tate;

float yoko;

float takasa;

int no2;

float tate2;

float yoko2;

float takasa2;


メンバ関数宣言

void bodydatadisplay();

void bodydatadisplay2();



クラスType1Robot1plus2に継承されるので


robotMIRAのクラスType1Robot1plus2型のオブジェクト宣言


Type1Robot1plus2 robotMIRA;


を実行すれば


クラスType1Robot1plus2型のオブジェクトrobotMIRAのメンバ変数



robotMIRA.no

robotMIRA.tate

robotMIRA.yoko

robotMIRA.takasa

robotMIRA.no1

robotMIRA.tate1

robotMIRA.yoko1

robotMIRA.takasa1

robotMIRA.no2

robotMIRA.tate2

robotMIRA.yoko2

robotMIRA.takasa2


クラスType1Robot1plus2型のオブジェクトrobotMIRAのメンバ関数


robotMIRA.bodydatadisplay()

robotMIRA.bodydatadisplay1()

robotMIRA.bodydatadisplay2()


が生成されるので


robotMIRA.no=1;

robotMIRA.tate=1.0;

robotMIRA.yoko=1.0;

robotMIRA.takasa=1.0;

robotMIRA.bodydatadisplay();


robotMIRA.no1=1;

robotMIRA.tate1=1.0;

robotMIRA.yoko1=1.0;

robotMIRA.takasa1=1.0;

robotMIRA.bodydatadisplay1();


robotMIRA.no2=1;

robotMIRA.tate2=1.0;

robotMIRA.yoko2=1.0;

robotMIRA.takasa2=1.0;

robotMIRA.bodydatadisplay2();


を実行すれば


ロボットの胴体につけられたナンバーは1です

ロボットの胴体の縦の長さは1メートルです

ロボットの胴体の横の長さは1メートルです

ロボットの胴体の高さの長さは1メートルです

ロボットの胴体につけられたナンバーは1ですよ

ロボットの胴体の縦の長さは1メートルですよ

ロボットの胴体の横の長さは1メートルですよ

ロボットの胴体の高さの長さは1メートルですよ

ロボットの胴体につけられたナンバーは1ですよ~~~ん

ロボットの胴体の縦の長さは1メートルですよ~~~ん

ロボットの胴体の横の長さは1メートルですよ~~~ん

ロボットの胴体の高さの長さは1メートルですよ~~~ん


が表示されると



          おもいませんか?




                                」



マックス「なんか・・・・



また何か 隠してるんじゃないのか?




ソーラー「ひくっ」


マックス「


新設したクラス


クラスType1Robot1plus2



クラスType1Robot1



メンバ変数宣言

int no;

float tate;

float yoko;

float takasa;

int no1;

float tate1;

float yoko1;

float takasa1;


メンバ関数宣言

void bodydatadisplay();

void bodydatadisplay1();



クラスType1Robot2



メンバ変数宣言

int no;

float tate;

float yoko;

float takasa;

int no2;

float tate2;

float yoko2;

float takasa2;


メンバ関数宣言

void bodydatadisplay();

void bodydatadisplay2();



継承されるとき


二重に


クラスRobotbodyから引き継いだ

メンバ変数宣言

int no;

float tate;

float yoko;

float takasa;

メンバ関数宣言

void bodydatadisplay();


が継承されているような気がするんだが・・・


もしかして


ビルドエラーが表示されたりとかしてな (´▽`*)」


ソーラー「!と、とりあえず


クラスType1Robot1plus2


を新設して


クラスType1Robot1

クラスType1Robot2



新設したクラス


クラスType1Robot1plus2



継承したプログラムを実行してみましょう。」


#include <iostream>


using namespace std;



class Robotbody{


public:

int no; //変数noはクラスRobotbodyのメンバ変数とよばれます

public:

float tate; //変数tateはクラスRobotbodyのメンバ変数とよばれます

public:

float yoko; //変数yokoはクラスRobotbodyのメンバ変数とよばれます

public:

float takasa; //変数takasaはクラスRobotbodyのメンバ変数とよばれます



public:

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


};



void Robotbody::bodydatadisplay() {


cout << "ロボットの胴体につけられたナンバーは" << no << "です" << "\n";

cout << "ロボットの胴体の縦の長さは" << tate << "メートルです" << "\n";

cout << "ロボットの胴体の横の長さは" << yoko << "メートルです" << "\n";

cout << "ロボットの胴体の高さの長さは" << takasa << "メートルです" << "\n";

}

//クラスRobotbodyのメンバ関数となっている自作関数bodydatadisplay()の定義をおこなっています




class Type1Robot1 :public Robotbody {


public:

int no1; //変数no1はクラスType1Robot1のメンバ変数とよばれます

public:

float tate1; //変数tate1はクラスType1Robot1のメンバ変数とよばれます

public:

float yoko1; //変数yoko1はクラスType1Robot1のメンバ変数とよばれます

public:

float takasa1; //変数takasa1はクラスType1Robot1のメンバ変数とよばれます



public:

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


};



void Type1Robot1::bodydatadisplay1() {


cout << "ロボットの胴体につけられたナンバーは" << no1 << "ですよ" << "\n";

cout << "ロボットの胴体の縦の長さは" << tate1 << "メートルですよ" << "\n";

cout << "ロボットの胴体の横の長さは" << yoko1 << "メートルですよ" << "\n";

cout << "ロボットの胴体の高さの長さは" << takasa1 << "メートルですよ" << "\n";

}

//クラスType1Robot1のメンバ関数となっている自作関数bodydatadisplay1()の定義をおこなっています




class Type1Robot2 :public Robotbody{


public:

int no2; //変数no2はクラスType1Robot2のメンバ変数とよばれます

public:

float tate2; //変数tate2はクラスType1Robot2のメンバ変数とよばれます

public:

float yoko2; //変数yoko2はクラスType1Robot2のメンバ変数とよばれます

public:

float takasa2; //変数takasa2はクラスType1Robot2のメンバ変数とよばれます



public:

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


};



void Type1Robot2::bodydatadisplay2() {


cout << "ロボットの胴体につけられたナンバーは" << no2 << "ですよ~~~ん" << "\n";

cout << "ロボットの胴体の縦の長さは" << tate2 << "メートルですよ~~~ん" << "\n";

cout << "ロボットの胴体の横の長さは" << yoko2 << "メートルですよ~~~ん" << "\n";

cout << "ロボットの胴体の高さの長さは" << takasa2 << "メートルですよ~~~ん" << "\n";

}

//クラスType1Robot2のメンバ関数となっている自作関数bodydatadisplay2()の定義をおこなっています



class Type1Robot1plus2 :public Type1Robot1,public Type1Robot2{

//🌞クラスType1Robot1plus2のメンバ変数宣言、メンバ関数宣言は設定していません


};




int main() {



Type1Robot1plus2 robotMIRA;


robotMIRA.no = 1;

robotMIRA.tate = 1.0;

robotMIRA.yoko = 1.0;

robotMIRA.takasa = 1.0;


robotMIRA.bodydatadisplay();



return 0;

}



プログラムの実行結果


エラー (アクティブ) E0266 "Type1Robot1plus2::no" があいまいです

エラー (アクティブ) E0266 "Type1Robot1plus2::tate" があいまいです

エラー (アクティブ) E0266 "Type1Robot1plus2::yoko" があいまいです

エラー (アクティブ) E0266 "Type1Robot1plus2::takasa" があいまいです

エラー (アクティブ) E0266 "Type1Robot1plus2::bodydatadisplay" があいまいです

エラー C2385 'no' へのアクセスがあいまいです。

エラー C2385 'tate' へのアクセスがあいまいです。

エラー C2385 'yoko' へのアクセスがあいまいです。

エラー C2385 'takasa' へのアクセスがあいまいです。

エラー C2385 'bodydatadisplay' へのアクセスがあいまいです。



てんC「あいまいです



たくさん表示されていますね。」


マックス「にぇえ?


なんで


ビルドエラーが表示されるんだ??」


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


クラスRobotbodyの


メンバ変数宣言

int no;

float tate;

float yoko;

float takasa;

メンバ関数宣言

void bodydatadisplay();

を受け継いだ


クラスType1Robot1


同じく


クラスRobotbodyの


メンバ変数宣言

int no;

float tate;

float yoko;

float takasa;

メンバ関数宣言

void bodydatadisplay();

を受け継いだ


クラスType1Robot2



クラスType1Robot1plus2


に継承しています。


ですので


robotMIRAのクラスType1Robot1plus2のオブジェクト宣言


Type1Robot1plus2 robotMIRA;


を実行し


生成される


Type1Robot1plus2型のオブジェクトrobotMIRAのメンバ変数


robotMIRA.no

robotMIRA.tate

robotMIRA.yoko

robotMIRA.takasa


Type1Robot1plus2型のオブジェクトrobotMIRAのメンバ関数


robotMIRA.bodydatadisplay()


を用いて


robotMIRA.no = 1;

robotMIRA.tate = 1.0;

robotMIRA.yoko = 1.0;

robotMIRA.takasa = 1.0;


robotMIRA.bodydatadisplay();



実行すれば


ビルド実行結果に


ロボットの胴体につけられたナンバーは1です

ロボットの胴体の縦の長さは1メートルです

ロボットの胴体の横の長さは1メートルです

ロボットの胴体の高さの長さは1メートルです


が表示されるはずなんです。


ですが


この


クラスRobotbodyの


メンバ変数宣言

int no;

float tate;

float yoko;

float takasa;

メンバ関数宣言

void bodydatadisplay();

を受け継いだ


クラスType1Robot1



同じく


クラスRobotbodyの


メンバ変数宣言

int no;

float tate;

float yoko;

float takasa;

メンバ関数宣言

void bodydatadisplay();

を受け継いだ


クラスType1Robot2



クラスType1Robot1plus2


に継承しているというところが問題なんです。


この状態では


クラスType1Robot1plus2は


クラスRobotbodyの


メンバ変数宣言

int no;

float tate;

float yoko;

float takasa;

メンバ関数宣言

void bodydatadisplay();


クラスType1Robot1

クラスType1Robot2


から


2重に


受け継いでいることになります。


ですので


エディタ上に


robotMIRAのクラスType1Robot1plus2のオブジェクト宣言


Type1Robot1plus2 robotMIRA;


を記述し


生成されるはずの


Type1Robot1plus2型のオブジェクトrobotMIRAのメンバ変数


robotMIRA.no

robotMIRA.tate

robotMIRA.yoko

robotMIRA.takasa


Type1Robot1plus2型のオブジェクトrobotMIRAのメンバ関数


robotMIRA.bodydatadisplay()


が用いられた


robotMIRA.no = 1;

robotMIRA.tate = 1.0;

robotMIRA.yoko = 1.0;

robotMIRA.takasa = 1.0;


robotMIRA.bodydatadisplay();



記述されていたとしても


ソースコードの

👇


robotMIRA.no = 1;

robotMIRA.tate = 1.0;

robotMIRA.yoko = 1.0;

robotMIRA.takasa = 1.0;


robotMIRA.bodydatadisplay();


👆

この部分を機械語に翻訳する際


コンパイラは


クラスRobotbodyから継承した


クラスType1Robot1の


メンバ変数宣言

メンバ関数宣言

となっている


メンバ変数宣言

int no;

float tate;

float yoko;

float takasa;

メンバ関数宣言

void bodydatadisplay();


にアクセスするよう


ソースコードの

👇


robotMIRA.no = 1;

robotMIRA.tate = 1.0;

robotMIRA.yoko = 1.0;

robotMIRA.takasa = 1.0;


robotMIRA.bodydatadisplay();


👆

この部分を機械語に翻訳したらいいのか


クラスRobotbodyから継承した


クラスType1Robot2の


メンバ変数宣言

メンバ関数宣言

となっている


メンバ変数宣言

int no;

float tate;

float yoko;

float takasa;

メンバ関数宣言

void bodydatadisplay();


にアクセスするよう


ソースコードの

👇


robotMIRA.no = 1;

robotMIRA.tate = 1.0;

robotMIRA.yoko = 1.0;

robotMIRA.takasa = 1.0;


robotMIRA.bodydatadisplay();


👆

この部分を機械語に翻訳したらいいのか


判断できないのです。」




🌞   🌞   🌞   🌞   🌞   🌞 



          普通



1つの親クラス(基本クラス)

から

子クラス(派生クラス)となる何も定義されていないクラスへ


クラスの継承がおこなわれるよう


ソースコードが記述されていると


親クラス(基本クラス)の


メンバ変数宣言

メンバ関数宣言


子クラス(派生クラス)へ引き継がれることになります。


この状態で


子クラス(派生クラス)型のオブジェクト宣言


を記述したなら


プログラムの実行時に


子クラス(派生クラス)型のオブジェクトのメンバ変数

子クラス(派生クラス)型のオブジェクトのメンバ関数


が生成されることになり


そして


子クラス(派生クラス)型のオブジェクトのメンバ変数

子クラス(派生クラス)型のオブジェクトのメンバ関数


が実行される際には


         


        💖親クラス(基本クラス)の💖




メンバ変数宣言

メンバ関数宣言


コンピュータがアクセスするよう


コンパイラはソースコードを機械語に翻訳する


ことになります。


コンパイラも迷うことはありません。


ですが


エディタ上で


          2つのクラス



クラスType1Robot1

クラスType1Robot2


何も定義されていないクラスType1Robot1plus2


に継承するようソースコードを記述し


さらに


robotMIRAのクラスType1Robot1plus2型のオブジェクト宣言


Type1Robot1plus2 robotMIRA;


を記述し


生成されるはずの


Type1Robot1plus2型のオブジェクトrobotMIRAのメンバ変数


robotMIRA.no

robotMIRA.tate

robotMIRA.yoko

robotMIRA.takasa


Type1Robot1plus2型のオブジェクトrobotMIRAのメンバ関数


robotMIRA.bodydatadisplay()


が用いられた


robotMIRA.no = 1;

robotMIRA.tate = 1.0;

robotMIRA.yoko = 1.0;

robotMIRA.takasa = 1.0;


robotMIRA.bodydatadisplay();


を記述しても


コンパイラは


クラスType1Robot1に継承されたクラスRobotbody

メンバ変数宣言

int no;

float tate;

float yoko;

float takasa;

メンバ関数宣言

void bodydatadisplay();


にアクセスするよう


ソースコードである


robotMIRA.no = 1;

robotMIRA.tate = 1.0;

robotMIRA.yoko = 1.0;

robotMIRA.takasa = 1.0;


robotMIRA.bodydatadisplay();



を機械語に翻訳したらいいのか


クラスType1Robot2に継承された


クラスRobotbody


メンバ変数宣言

int no;

float tate;

float yoko;

float takasa;

メンバ関数宣言

void bodydatadisplay();


にアクセスするよう


ソースコード


robotMIRA.no = 1;

robotMIRA.tate = 1.0;

robotMIRA.yoko = 1.0;

robotMIRA.takasa = 1.0;


robotMIRA.bodydatadisplay();


を機械語に翻訳したらいいのか


判断できないため


ビルド実行時に


ビルドエラーが表示されるというわけです」



🌞   🌞   🌞   🌞   🌞   🌞 





ソーラー「というわけで


マックスさんの予想通り今のプログラムは


ビルド実行できないのでした。😊


ちゃん、ちゃん」


マックス「つまり


親クラス(基本クラス)の


メンバ変数宣言

メンバ関数宣言



クラスA

クラスB

クラスC

クラスD

クラスE


に継承したとするだろう


その


クラスA

クラスB

クラスC

クラスD

クラスE



全部


さらに


別のクラスFへ


継承すると


その別のクラスFは


ある親クラス(基本クラス)の


メンバ変数宣言

メンバ関数宣言



5重


に引き継ぐことになるんだろう。


となると


エディタ上で


クラスF型のオブジェクト宣言を記述し


親クラス(基本クラス)のメンバ変数が用いられた


クラスF型のオブジェクトのメンバ変数


親クラス(基本クラス)のメンバ関数が用いられた


クラスFのオブジェクトのメンバ関数


を記述しても


コンパイラは


(´▽`*)どのクラスに継承された(´▽`*)


親クラス(基本クラス)の


メンバ変数宣言

メンバ関数宣言


にアクセスしたらいいか判断できず


ソースコードを翻訳できないってわけだ


親クラス(基本クラス)の


メンバ変数宣言

メンバ関数宣言


にアクセスできないってことは


親クラス(基本クラス)の


メンバ変数宣言

メンバ関数宣言


が継承されているにも関わらず


親クラス(基本クラス)の


メンバ変数

メンバ関数


は使用できないってわけだ。


ていうか


こんなことは


クラスの多重継承を行っていったらいくらでも


しょっちゅう起きるてくるんじゃないか?」



ソーラー「そうなんです。


そこで


            💖仮想クラス💖


の登場です



上記のような事態を避けるため



             💖他のクラスへ💖



         💖ひんぱんに継承されるクラスを💖



         💖クラスの継承を行う際に💖💖💖💖💖💖💖💖💖💖💖 



            💖仮想クラス💖



に設定します。




       💖クラスの継承を行う際に💖💖💖💖💖💖💖💖💖💖💖 



            💖仮想クラス💖



に設定したい継承される側のクラスには


virtualをくっつけます。


例えば今のプログラムの例でいえば


クラスRobotbodyを


クラスType1Robot1


クラスType1Robot2


に継承する際に


クラスRobotbodyに


virtual


をくっつけて


Type1Robot1:public virtual Robotbody


Type2Robot1:public virtual Robotbody


と記述すれば


Robotbody



            💖仮想クラス💖



設定したことになります。



これまた


簡単ですね。」


マックス「Robotbodyが仮想クラスに設定されると


どのようなことが起こるんだ?」



ソーラー「


例えば



           あるクラスを




       💖クラスの継承を行う際に💖💖💖💖💖💖💖💖💖💖💖 

          


           💖仮想クラス💖


に設定して



       💖仮想クラスとなった親クラス(基本クラス)の💖


メンバ変数宣言

メンバ関数宣言



クラスA

クラスB

クラスC

クラスD

クラスE


に継承したとします


その


クラスA

クラスB

クラスC

クラスD

クラスE



全部


さらに


別のクラスFへ


継承すると


その別のクラスFは


ある親クラス(基本クラス)の


メンバ変数宣言

メンバ関数宣言



5つのクラスから


5重


に引き継ぐことになりますが


それに関わらず


エディタ上で


クラスF型のオブジェクト宣言を記述し


親クラス(基本クラス)のメンバ変数が用いられた


クラスF型のオブジェクトのメンバ変数


親クラス(基本クラス)のメンバ関数が用いられた


クラスF型のオブジェクトのメンバ関数


を記述した場合


コンパイラは


親クラス(基本クラス)の


メンバ変数宣言

メンバ関数宣言


にアクセスするよう


ソースコードを翻訳することになるので


ビルドエラーは表示されません。


どのクラスに継承された


親クラス(基本クラス)の


メンバ変数宣言

メンバ関数宣言


にアクセスしたらいいか判断できず


ソースコードを翻訳できないということはないわけだね。」


マックス「・・・・・」


ソーラー「わかりにくかったかな💦


詳しくは


先ほどのプログラムの


親クラス(基本クラス)


Robotbody




      💖クラスの継承を行う際に💖💖💖💖💖💖💖💖💖💖💖 


          

           💖仮想クラス💖



         💖virtual Robotbody💖



に設定しなおして


プログラムをビルド実行してみようよ。


どのようなことがおこるかな?


こんどは


ビルドエラーが表示されずちゃんと


ビルド実行できるかな?


そのプログラムはこちらです(´▽`*)」

👇

#include <iostream>


using namespace std;



class Robotbody{


public:

int no; //変数noはクラスRobotbodyのメンバ変数とよばれます

public:

float tate; //変数tateはクラスRobotbodyのメンバ変数とよばれます

public:

float yoko; //変数yokoはクラスRobotbodyのメンバ変数とよばれます

public:

float takasa; //変数takasaはクラスRobotbodyのメンバ変数とよばれます



public:

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


};



void Robotbody::bodydatadisplay() {


cout << "ロボットの胴体につけられたナンバーは" << no << "です" << "\n";

cout << "ロボットの胴体の縦の長さは" << tate << "メートルです" << "\n";

cout << "ロボットの胴体の横の長さは" << yoko << "メートルです" << "\n";

cout << "ロボットの胴体の高さの長さは" << takasa << "メートルです" << "\n";

}

//クラスRobotbodyのメンバ関数となっている bodydatadisplay()の定義をおこなっています




class Type1Robot1 :public virtual Robotbody{


public:

int no1; //変数no1はクラスType1Robot1のメンバ変数とよばれます

public:

float tate1; //変数tate1はクラスType1Robot1のメンバ変数とよばれます

public:

float yoko1; //変数yoko1はクラスType1Robot1のメンバ変数とよばれます

public:

float takasa1; //変数takasa2はクラスType1Robot1のメンバ変数とよばれます



public:

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


};



void Type1Robot1::bodydatadisplay1() {


cout << "ロボットの胴体につけられたナンバーは" << no1 << "ですよ" << "\n";

cout << "ロボットの胴体の縦の長さは" << tate1 << "メートルですよ" << "\n";

cout << "ロボットの胴体の横の長さは" << yoko1 << "メートルですよ" << "\n";

cout << "ロボットの胴体の高さの長さは" << takasa1 << "メートルですよ" << "\n";

}

//クラスType1Robot1のメンバ関数となっている自作関数bodydatadisplay1()の定義をおこなっています




class Type1Robot2 :public virtual Robotbody {


public:

int no2; //変数no2はクラスType1Robot2のメンバ変数とよばれます

public:

float tate2; //変数tate1はクラスType1Robot2のメンバ変数とよばれます

public:

float yoko2; //変数yoko1はクラスType1Robot2のメンバ変数とよばれます

public:

float takasa2; //変数takasa2はクラスType1Robot2のメンバ変数とよばれます



public:

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


};



void Type1Robot2::bodydatadisplay2() {


cout << "ロボットの胴体につけられたナンバーは" << no2 << "ですよ~~~ん" << "\n";

cout << "ロボットの胴体の縦の長さは" << tate2 << "メートルですよ~~~ん" << "\n";

cout << "ロボットの胴体の横の長さは" << yoko2 << "メートルですよ~~~ん" << "\n";

cout << "ロボットの胴体の高さの長さは" << takasa2 << "メートルですよ~~~ん" << "\n";

}

//クラスType1Robot2のメンバ関数となっている自作関数bodydatadisplay2()の定義をおこなっています



class Type1Robot1plus2 :public Type1Robot1,public Type1Robot2{

//🌞クラスType1Robot1plus2のメンバ変数宣言、メンバ関数宣言は設定していません


};




int main() {



Type1Robot1plus2 robotMIRA;


robotMIRA.no = 1;

robotMIRA.tate = 1.0;

robotMIRA.yoko = 1.0;

robotMIRA.takasa = 1.0;


robotMIRA.bodydatadisplay();


return 0;

}


ビルド実行結果


ロボットの胴体につけられたナンバーは1です

ロボットの胴体の縦の長さは1メートルです

ロボットの胴体の横の長さは1メートルです

ロボットの胴体の高さの長さは1メートルです


マックス「やったな ソーラー


クラスRobotbodyを


クラスType1Robot1


クラスType1Robot2


に継承する際に


クラスRobotbodyに


virtual


をくっつけて


Type1Robot1:public virtual Robotbody


Type2Robot1:public virtual Robotbody



親クラス(基本クラス)になるRobotbodyを



             💖仮想クラス💖


に設定したので


robotMIRA.no = 1;

robotMIRA.tate = 1.0;

robotMIRA.yoko = 1.0;

robotMIRA.takasa = 1.0;


robotMIRA.bodydatadisplay();


を実行する際にも


コンパイラは


クラスType1Robot1


クラスType1Robot2


のどちらのクラスに継承された


親クラス(基本クラス)Robotbodyのメンバ変数宣言


int no;

float tate;

float yoko;

float takasa;


親クラス(基本クラス)Robotbodyのメンバ関数宣言


void bodydatadisplay()


にアクセスしたらいいのか迷うことなく



親クラス(基本クラス)Robotbody のメンバ変数宣言


int no;

float tate;

float yoko;

float takasa;


親クラス(基本クラス)Robotbodyのメンバ関数宣言


void bodydatadisplay()



アクセスするようソースコードを機械語に翻訳したので


プログラムを実行することができるようになったわけだ。」






























別のクラスである


Type1Robotdatadisplayに継承するには


派生クラスとなるType1Robotdatadisplayのクラス宣言を


次のように記述します

👇


class Type1Robotdatadisplay:public Robotbodydatadisplay{

/*🌞クラスType1Robotdatadisplayのメンバ変数宣言、メンバ関数宣言

は設定していません

ですので

クラスType1Robotdatadisplayのメンバ関数の定義がおこなわれることはありません🌞*/


};


いかがですか?                                                          」


マックス「ここまでは先のエピソードと同じだな


くくっ 簡単だ~い」


ソーラー「今度は


クラスRobotbodydatadisplay

別のクラス


Type1plusRobotdatadisplayに継承してみたいと思います。


クラスType1plusRobotdatadisplayのクラス宣言と


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


class Type1plusRobotdatadisplay{

/*🌞クラスType1plusRobotdatadisplayのメンバ変数宣言、メンバ関数宣言

は設定していません

ですので

クラスType1plusRobotdatadisplayのメンバ関数の定義がおこなわれることはありません🌞*/


};


とします。」



マックス「さっきは


クラスRobotbodydatadisplay



クラスType1Robotdatadisplayに継承したよな😊


今度は


クラスRobotbodydatadisplay



クラスType1plusRobotdatadisplayに継承するのか😊


ソーラー「そうなんです。


試行錯誤の末に


このようなことはよくあります。」




マックス「ほほう


それで


クラスType1plusRobotdatadisplayの


クラス宣言では


メンバ変数宣言

メンバ関数宣言



記述されていないな」


ソーラー「そうです。


もちろん


クラスType1plusRobotdatadisplayの


クラス宣言に


メンバ変数宣言

メンバ関数宣言


が記述されていなくても


クラスRobotbodydatadisplay



メンバ変数宣言

メンバ関数宣言



クラスType1plusRobotdatadisplayに


継承することができます。



クラスType1Robotdatadisplay

クラスType1plusRobotdatadisplay

👆

これら2つのクラスを


別のクラス


Type1plus2Robotdatadisplayに継承したいと思います。


クラスType1plus2Robotdatadisplayのクラス宣言



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


class Type1plus2Robotdatadisplay{

/*🌞クラスType1plus2Robotdatadisplayのメンバ変数宣言、メンバ関数宣言

は設定していません

ですので

クラスType1plus2Robotdatadisplayのメンバ関数の定義がおこなわれることはありません🌞*/


};


とします。


そのとき


クラスType1Robotdatadisplay

クラスType1plusRobotdatadisplay

👆

これら2つのクラスを


Type1plus2Robotdatadisplayに継承するには


派生クラスとなるType1plus2Robotdatadisplayのクラス宣言と


そのメンバ関数の定義を


次のように記述します

👇


class Type1plus2Robotdatadisplay:public Type1Robotdatadisplay,public Type1plusRobotdatadisplay{

/*🌞クラスType1plus2Robotdatadisplayのメンバ変数宣言、メンバ関数宣言

は設定していません

ですので

クラスType1plus2Robotdatadisplayのメンバ関数の定義がおこなわれることはありません🌞*/


};


いかがですか? 」



マックス「ほほう


クラスRobotbodydatadisplay


を継承した



     クラスType1Robotdatadisplay



クラスRobotbodydatadisplay


を継承した


     クラスType1plusRobotdatadisplay




     クラスType1plus2Robotdatadisplay


に継承しているのか?


こんな風に記述するのか?



😊   😊   😊   😊   😊   😊   😊


そうなんです。


class Type1plus2Robotdatadisplay:public Type1Robotdatadisplay,public Type1plusRobotdatadisplay{

/*🌞クラスType1plus2Robotdatadisplayのメンバ変数宣言、メンバ関数宣言

は設定していません

ですので

クラスType1plus2Robotdatadisplayのメンバ関数の定義がおこなわれることはありません🌞*/


};

と記述します。


クラスType1Robotdatadisplayが

クラスRobotbodydatadisplay

を継承しているからといって


👆の命令文の


public Type1Robotdatadisplay

の部分を


public Type1Robotdatadisplay:public Robotbodydatadisplay


と書き換えたり


クラスType1plusRobotdatadisplayが

クラスRobotbodydatadisplay


を継承しているからといって


👆の命令文の


public Type1plusRobotdatadisplay

の部分を

public Type1plusRobotdatadisplay:public Robotbodydatadisplay


と書き換えて


class Type1plus2Robotdatadisplay:public Type1Robotdatadisplay:public Robotbodydatadisplay,public Type1plusRobotdatadisplay:public Robotbodydatadisplay{

/*🌞クラスType1plus2Robotdatadisplayのメンバ変数宣言、メンバ関数宣言

は記述設定していません

ですので

クラスType1plus2Robotdatadisplayのメンバ関数の定義がおこなわれることはありません🌞*/


のように記述することはできません。


このようにクラスの継承が記述されていると


ビルドエラーが表示されます。


                     solarplexussより



😊   😊   😊   😊   😊   😊   😊


マックス「なんか


ひたすらクラスRobotbodydatadisplay


を継承していることになるんじゃないか?」





マックス「たとえば


👇

クラスRobotbodydatadisplayを継承している


クラスType1Robotdatadisplay


クラスRobotbodydatadisplayを継承している


クラスType1plusRobotdatadisplay

👆



クラスType1plus2Robotdatadisplay


に継承したということは


結局


クラスRobotbodydatadisplay


クラスType1plus2Robotdatadisplay


に継承したことになるんじゃないか? 」


ソーラー「実はそうなんです。」



マックス「


くっくっ


ということは


クラスType1plus2Robotdatadisplay は


ロボットの胴体につけられたナンバー

ロボットの胴体の縦の長さ

ロボットの胴体の横の長さ

ロボットの胴体の高さの長さ


を表示する機能をもつ


クラスRobotbodydatadisplay


を継承することになるよな


いいんじゃないか?


ちょうどいいじゃないか


もともとソーラーの設定により


クラスType1Robotdatadisplayは


ロボットの胴体につけられたナンバー

ロボットの胴体の縦の長さ

ロボットの胴体の横の長さ

ロボットの胴体の高さの長さ


を表示する機能をもつ


クラスRobotbodydatadisplay


を継承するために


作られたクラスだからな


同じような名前 Type1を使ったクラス


Type1plus2Robotdatadisplayも


ロボットの胴体につけられたナンバー

ロボットの胴体の縦の長さ

ロボットの胴体の横の長さ

ロボットの胴体の高さの長さ


を表示する機能をもつ


クラスというわけだ。」


ソーラー「ところで



ロボットの胴体につけられたナンバー

ロボットの胴体の縦の長さ

ロボットの胴体の横の長さ

ロボットの胴体の高さの長さ


を表示する機能をもつ


クラスRobotbodydatadisplay



直接


次のように


クラス Type1plus2Robotdatadisplay


に継承する方法がありますね。

👇

class Type1plus2Robotdatadisplay:public Robotbodydatadisplay{

/*🌞クラスType1plus2Robotdatadisplayのメンバ変数宣言、メンバ関数宣言

は設定していません

ですので

クラスType1plus2Robotdatadisplayのメンバ関数の定義がおこなわれることはありません🌞*/


};


以上の   


2つの継承方法では


いずれの場合でも


クラスType1plus2Robotdatadisplayに


ロボットの胴体につけられたナンバー

ロボットの胴体の縦の長さ

ロボットの胴体の横の長さ

ロボットの胴体の高さの長さ


を表示する機能をもつ


クラスRobotbodydatadisplay



継承されることになりますが・・・・・


しかし


ここで問題が発生してきます。」


マックス「問題? どこに? そんなことはおこらないだろう?


さすがに


クラスRobotbodydatadisplay


を継承するのが目的なら


この継承方法は

👇

class Type1plus2Robotdatadisplay:public Type1Robotdatadisplay,public Type1plusRobotdatadisplay{

/*🌞クラスType1plus2Robotdatadisplayのメンバ変数宣言、メンバ関数宣言

は設定していません

ですので

クラスType1plus2Robotdatadisplayのメンバ関数の定義がおこなわれることはありません🌞*/


};

👆

めんどくさい感じがするが・・・


ソーラー「とりあえず


クラスRobotbodydatadisplay


を継承した



     クラスType1Robotdatadisplay



クラスRobotbodydatadisplay


を継承した


     クラスType1plusRobotdatadisplay




     クラスType1plus2Robotdatadisplay


に継承したプログラムを実行してみたいと思います


どのようなビルド実行結果がでてくるかな~~😊」


マックス「だいじょ~ぶ


だいじょ~ぶ


何も別に問題ないだろう。」


ソーラー


「では


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


#include <iostream>


using namespace std;



class Robotbodydatadisplay {


public:

int no; //変数noはクラスRobotbodydatadisplayのメンバ変数とよばれます

public:

float tate; //変数tateはクラスRobotbodydatadisplayのメンバ変数とよばれます

public:

float yoko; //変数yokoはクラスRobotbodydatadisplayのメンバ変数とよばれます

public:

float takasa; //変数takasaはクラスRobotbodydatadisplayのメンバ変数とよばれます



public:

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


};



void Robotbodydatadisplay::bodydatadisplay() {


cout << "ロボットの胴体につけられたナンバーは" << no << "です" << "\n";

cout << "ロボットの胴体の縦の長さは" << tate << "メートルです" << "\n";

cout << "ロボットの胴体の横の長さは" << yoko << "メートルです" << "\n";

cout << "ロボットの胴体の高さの長さは" << takasa << "メートルです" << "\n";

}

//クラスRobotbodydatadisplayのメンバ関数となっている自作関数void bodydatadisplay()の定義をおこなっています




class Type1Robotdatadisplay :public Robotbodydatadisplay {

/*🌞クラスType1Robotdatadisplayのメンバ変数宣言、メンバ関数宣言

は設定していません

ですので

クラスType1Robotdatadisplayのメンバ関数の定義がおこなわれることはありません🌞*/


};



class Type1plusRobotdatadisplay :public Robotbodydatadisplay {

/*🌞クラスType1plusRobotdatadisplayのメンバ変数宣言、メンバ関数宣言

は設定していません

ですので

クラスType1plusRobotdatadisplayのメンバ関数の定義がおこなわれることはありません🌞*/


};




class Type1plus2Robotdatadisplay :public Type1Robotdatadisplay, public Type1plusRobotdatadisplay {

/*🌞クラスType1plus2Robotdatadisplayのメンバ変数宣言、メンバ関数宣言

は設定していません

ですので

クラスType1plus2Robotdatadisplayのメンバ関数の定義がおこなわれることはありません🌞*/


};


int main() {



Type1plus2Robotdatadisplay robotMIRA;


robotMIRA.no = 1;

robotMIRA.tate = 1.0;

robotMIRA.yoko = 1.0;

robotMIRA.takasa = 1.0;


robotMIRA.bodydatadisplay();


return 0;

}


ビルド実行結果


エラー C2385 'yoko' へのアクセスがあいまいです。

エラー C2385 'tate' へのアクセスがあいまいです。

エラー C2385 'takasa' へのアクセスがあいまいです。

エラー C2385 'no' へのアクセスがあいまいです。

エラー C2385 'bodydatadisplay' へのアクセスがあいまいです。

エラー (アクティブ) E0266 "Type1plus2Robotdatadisplay::yoko" があいまいです

エラー (アクティブ) E0266 "Type1plus2Robotdatadisplay::tate" があいまいです

エラー (アクティブ) E0266 "Type1plus2Robotdatadisplay::takasa" があいまいです

エラー (アクティブ) E0266 "Type1plus2Robotdatadisplay::no" があいまいです

エラー (アクティブ) E0266 "Type1plus2Robotdatadisplay::bodydatadisplay" があいまいです



マックス「なんだ?  このあいまいな ビルドエラー表示は?」


てんC「あいまいが いっぱいですね。


なぜ あいまいなのでしょうか?」


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


robotMIRAのType1plus2Robotdatadisplay型のオブジェクト宣言


Type1plus2Robotdatadisplay robotMIRA;


が実行されています。


このとき


Type1plus2Robotdatadisplay型のオブジェクトrobotMIRAのメンバ変数


robotMIRA.no

robotMIRA.tate

robotMIRA.yoko

robotMIRA.takasa


Type1plus2Robotdatadisplay型のオブジェクトrobotMIRAのメンバ関数


robotMIRA.bodydatadisplay();


が生成されることになります。


ですので


robotMIRA.no = 1;

robotMIRA.tate = 1.0;

robotMIRA.yoko = 1.0;

robotMIRA.takasa = 1.0;


robotMIRA.bodydatadisplay();


実行できるというわけです。」


マックス「じゃあビルドエラーが表示されないんじゃないか?

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

作者を応援しよう!

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

応援したユーザー

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

新規登録で充実の読書を

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

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

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