通常の自作関数と違い オブジェクトのメンバ関数を実行することにより オブジェクトのメンバ変数、静的メンバ変数に格納される値を 変更することができます。

ソーラー「さあて


このエピソードのタイトルは


☆  ☆  ☆  ☆  ☆  ☆  ☆  ☆

通常の自作関数と違い オブジェクトのメンバ関数を実行することにより オブジェクトのメンバ変数、静的メンバ変数に格納される値を 変更することができます。

☆  ☆  ☆  ☆  ☆  ☆  ☆  ☆


となっていますが


正式には


☆  ☆  ☆  ☆  ☆  ☆  ☆  ☆

通常、自作関数が実行されたとき


自作関数内で変数宣言された変数は


格納されたデータとともに消去されますが


オブジェクトのメンバ関数を実行した場合は


オブジェクトのメンバ変数、オブジェクトの静的メンバ変数は


消去されず


オブジェクトのメンバ変数、オブジェクトの静的メンバ変数に


格納されたデータも消去されません

☆  ☆  ☆  ☆  ☆  ☆  ☆  ☆


となっています。


マックス「なにぃ


いまさら そのネタをもってくるのか?


いままで


            🌞さんざん


オブジェクトのメンバ関数を実行することにより

オブジェクトのメンバ変数、オブジェクトの静的メンバ変数に格納される値を

変更してきたじゃないか


その際


オブジェクトのメンバ変数、オブジェクトの静的メンバ変数は


格納されたデータとともに消去されなかっただろう



そもそも


オブジェクトのメンバ変数、オブジェクトの静的メンバ変数は


オブジェクトのメンバ関数内で定義された変数ではないんじゃないか?」



ソーラー「では・・・


すこしだけ


いいかえると


main関数内で


オブジェクトのメンバ関数が実行されて


オブジェクトのメンバ変数、静的メンバ変数に格納された値が


変更されたとしても


つまり


オブジェクトのメンバ関数の実行後も


オブジェクトのメンバ変数、静的メンバ変数は消去されることなく


オブジェクトのメンバ変数、静的メンバ変数に格納された


値は変更されたまま保存されることになります。


ということなんです。」


マックス「ほとんどかわっていない・・・


えぇ?


何をいまさら・・・


そんなの当たり前じゃないか~い」


solarplexuss「そういう仕組みじゃなかったっけ??」


ソーラー「そうなんです


このエピソードでは


その当たり前のことを確認してみようというわけです。


 まずは次のプログラムをご覧ください」



#include <iostream>


using namespace std;


class Cube{


public:

int no;

public:

float tate;

public:

float yoko;

public:

float takasa;


public:

Cube();


/*🌞🌞🌞クラスCubeのコンストラクタCube() のメンバ関数宣言を行っています*/


public:

void display(); //自作関数display()のクラスCubeのメンバ関数宣言を行っています


public:

static int a;

/*🌞🌞🌞ここですよ~ん🌞🌞🌞

静的メンバ変数aのCubeのメンバ変数宣言を行っています*/


};


Cube::Cube() {


no = 0;

tate = 0.0;

yoko = 0.0;

takasa = 0.0;


cout << "生成されたオブジェクトのメンバ変数を初期化しました" << "\n";


}

/*👆🌞

クラスCubeのコンストラクタCube()の定義を行っています

🌞*/



void Cube::display() {


cout << a << "回目のオブジェクトcube1のメンバ関数cube1.display()を実行しました" << "\n";


a++;

cout <<"cube1.aの値は" << a << "になりました" << "\n";

no++;

cout << "立方体につけられたナンバーは" << no << "です" << "\n";

tate++;

cout << "立方体の縦の長さは" << tate << "です" << "\n";

yoko++;

cout << "立方体の横の長さは" << yoko << "です" << "\n";

takasa++;

cout << "立方体の高さの長さは" << takasa << "です" << "\n";


}


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


int Cube::a = 1;



//👆🌞🌞🌞ここです🌞🌞🌞静的メンバ変数aの初期化を行っています

//👆🌞🌞🌞静的メンバ変数aの格納する値は1になります



int main() {


Cube cube1;


//👆cube1のクラスCube型のオブジェクト宣言をおこなっています

/*🌞このとき オブジェクトcube1のコンストラクタが自動的に実行されています*/


cout << "オブジェクトcube1の静的メンバ変数cube1.aに代入された数値データは" << cube1.a << "です" << "\n";


cube1.display();


return 0;

}


プログラムの実行結果


生成されたオブジェクトのメンバ変数を初期化しました

オブジェクトcube1の静的メンバ変数cube1.aに代入された数値データは1です

1回目のオブジェクトcube1のメンバ関数cube1.display()を実行しました

cube1.aの値は2になりました

立方体につけられたナンバーは1です

立方体の縦の長さは1です

立方体の横の長さは1です

立方体の高さの長さは1です




ソーラー「


新たに設定し直された


クラスCubeのメンバ関数display()の定義


void Cube::display() {


cout << a << "回目のオブジェクトcube1のメンバ関数cube1.display()を実行しました" << "\n";


a++;

cout <<"cube1.aの値は" << a << "になりました" << "\n";

no++;

cout << "立方体につけられたナンバーは" << no << "です" << "\n";

tate++;

cout << "立方体の縦の長さは" << tate << "です" << "\n";

yoko++;

cout << "立方体の横の長さは" << yoko << "です" << "\n";

takasa++;

cout << "立方体の高さの長さは" << takasa << "です" << "\n";


}


では


a++;

no++;

tate++;

yoko++;

takasa++;


が用いられています。




a++;



a=a+1;


を表す命令文ですね。


このプログラムで


cube1のクラスCube型のオブジェクト宣言


Cube cube1;


の実行後


クラスCube型のオブジェクトcube1のコンストラクタが実行されます


つまり


クラスCubeのコンストラクタの定義


Cube::Cube() {


no = 0;

tate = 0.0;

yoko = 0.0;

takasa = 0.0;


cout << "生成されたオブジェクトのメンバ変数を初期化しました" << "\n";


}



no

tate

yoko

takasa


cube1.no 

cube1.tate 

cube1.yoko 

cube1.takasa


が代入されて

cube1.no=0; 

cube1.tate=0.0; 

cube1.yoko=0.0; 

cube1.takasa=0.0; 


が実行されるので

 

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


cube1.no

cube1.tate

cube1.yoko

cube1.takasa



0

0.0

0.0

0.0


初期化されます


そして


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


cube1.display();


が実行されると


cube1のクラスCube型のオブジェクト宣言


Cube cube1;


によって作製された


クラスCube型のオブジェクトcube1の静的メンバ変数


cube1.a


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

cube1.no

cube1.tate

cube1.yoko

cube1.takasa



クラスCubeのメンバ関数であるdisplay()の定義

👇

void Cube::display() {


cout << a << "回目のオブジェクトcube1のメンバ関数cube1.display()を実行しました" << "\n";


a++;

cout <<"cube1.aの値は" << a << "になりました" << "\n";

no++;

cout << "立方体につけられたナンバーは" << no << "です" << "\n";

tate++;

cout << "立方体の縦の長さは" << tate << "です" << "\n";

yoko++;

cout << "立方体の横の長さは" << yoko << "です" << "\n";

takasa++;

cout << "立方体の高さの長さは" << takasa << "です" << "\n";


}


a

no

tate

yoko

takasa


に代入された


cout <<cube1.a<< "回目のオブジェクトcube1のメンバ関数cube1.display()を実行しました"<< "\n";


(cube1.a)++;

cout <<"cube1.aの値は" <<cube1.a<< "になりました" << "\n";

(cube1.no)++;

cout << "立方体につけられたナンバーは" << cube1.no << "です" << "\n";

(cube1.tate)++;

cout << "立方体の縦の長さは" << cube1.tate << "です" << "\n";

(cube1.yoko)++;

cout << "立方体の横の長さは" << cube1.yoko << "です" << "\n";

(cube1.takasa)++;

cout << "立方体の高さの長さは" << cube1.takasa << "です" << "\n";


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


このとき


Cubeのクラス宣言内の


aの静的メンバ変数宣言


static int a;


aのメンバ変数宣言


int Cube::a = 1;


が実行されていることにより


どのようなオブジェクト宣言


例えば

Cube cube1;

Cube cube2;

Cube ray;

のいずれか

が実行されても


生成される

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

cube1.a

cube2.a

ray.a


は1の値をもつことになります。


たとえば


cube1のクラスCube型のオブジェクト宣言が行われたなら


生成されるそのクラスCube型のオブジェクトcube1のメンバ変数


cube1.aは1の値をもつことになります。


cube2のクラスCube型のオブジェクト宣言が行われたなら


生成されるそのクラスCube型のオブジェクトcube2のメンバ変数


cube2.aは1の値をもつことになります。


ray.aのクラスCube型のオブジェクト宣言が行われたなら


生成されるそのクラスCube型のオブジェクトrayのメンバ変数


ray.aは1の値をもつことになるというわけです。


(ただし ここでは


Cube cube1;

Cube cube2;

Cube ray;

のいずれかが実行されるとします)



ここでは


cube1のオブジェクト宣言が行われているので


生成されるオブジェクトの静的メンバ変数


cube1.a


は1の値をもつことになります。


ですので


cout <<cube1.a<< "回目のオブジェクトcube1のメンバ関数cube1.display()を実行しました" << "\n";


のビルド実行結果は


1回目のオブジェクトcube1のメンバ関数cube1.display()を実行しました


となります。


次に


(cube1.a)++;



cube1.a=cube1.a+1;


をあらわしていますね。


cube1.aは1の値に初期化されていたので


cube1.a=cube1.a+1;


が実行されると


cube1.aが今持っている値1に1を足したものが


cube1.aに代入されることになります


ですので


cube1.aは2の値をもつことになります。


となると


cout <<"cube1.aの値は" << cube1.a << "になりました" << "\n";



のビルド実行結果は


cube1.aの値は2になりました


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


cube1.aの格納する値は2になりました


か・・・ふふっ😊


同様に

cout <<cube1.a<< "回目のオブジェクトcube1のメンバ関数cube1.display()を実行しました"<< "\n";

(cube1.a)++;

cout <<"cube1.aの値は" <<cube1.a<< "になりました" << "\n";


の実行の後


(cube1.no)++;

cout << "立方体につけられたナンバーは" << cube1.no << "です" << "\n";

(cube1.tate)++;

cout << "立方体の縦の長さは" << cube1.tate << "です" << "\n";

(cube1.yoko)++;

cout << "立方体の横の長さは" << cube1.yoko << "です" << "\n";

(cube1.takasa)++;


の実行により


cube1.noの格納する値は1になり

cube1.tateの格納する値は1になり

cube1.yokoの格納する値は1になり

cube1.takasaの格納する値は1になり


ビルド実行結果


立方体につけられたナンバーは1です

立方体の縦の長さは1です

立方体の横の長さは1です

立方体の高さの長さは1です


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


どうかな?(*´▽`*)」


マックス「う~ん ふつう・・・だな」


ソーラー「


そして


          このプログラムの最大のポイントは



クラスCube型のオブジェクトcube1のメンバ関数cube1.display()の実行により


プログラムの実行結果


cube1.aの値は2になりました

立方体につけられたナンバーは1です

立方体の縦の長さは1です

立方体の横の長さは1です

立方体の高さの長さは1です


が表示されたということなんです」


マックス「それの何が最大のポイントなのかわからんな」


ソーラー「ところで


クラスCubeのメンバ関数display()


は自作関数でした。


クラスCube型のオブジェクトcube1のメンバ関数である


cube1.display()が実行されると


クラスCubeのメンバ関数であるdisplay()の定義


void Cube::display() {


cout << a << "回目のオブジェクトcube1のメンバ関数cube1.display()を実行しました" << "\n";


a++;

cout << "cube1.aの値は" << a << "になりました" << "\n";

no++;

cout << "立方体につけられたナンバーは" << no << "です" << "\n";

tate++;

cout << "立方体の縦の長さは" << tate << "です" << "\n";

yoko++;

cout << "立方体の横の長さは" << yoko << "です" << "\n";

takasa++;

cout << "立方体の高さの長さは" << takasa << "です" << "\n";


}

a

no

tate

yoko

takasa


cube1.a

cube1.no

cube1.tate

cube1.yoko

cube1.takasa



代入された


cout <<cube1.a<< "回目のオブジェクトcube1のメンバ関数cube1.display()を実行しました"<< "\n";


(cube1.a)++;

cout <<"cube1.aの値は" <<cube1.a<< "になりました" << "\n";

(cube1.no)++;

cout << "立方体につけられたナンバーは" << cube1.no << "です" << "\n";

(cube1.tate)++;

cout << "立方体の縦の長さは" << cube1.tate << "です" << "\n";

(cube1.yoko)++;

cout << "立方体の横の長さは" << cube1.yoko << "です" << "\n";

(cube1.takasa)++;

cout << "立方体の高さの長さは" << cube1.takasa << "です" << "\n";


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



クラスCubeのメンバ関数display()は自作関数なので


クラスCube型のオブジェクトcube1のメンバ関数cube1.display()が実行されて


プログラムの実行結果


cube1.aの値は2になりました

立方体につけられたナンバーは1です

立方体の縦の長さは1です

立方体の横の長さは1です

立方体の高さの長さは1です


になったとしても


本当は


cube1.aの格納する値は2に

cube1.noの格納する値は1に

cube1.tateの格納する値は1に

cube1.yokoの格納する値は1に

cube1.takasaの格納する値は1に


なっていないかも


しれないということなんです。」


マックス「はえ???????」


solarplexuss「??????????」



ソーラー「


つまり


main関数内で変数宣言された


変数aを


自作関数内で定義された変数bに代入しても


変数aから変数bへ値渡しが行われるのみで


main関数内で変数宣言された


変数aに格納された数値は変化しませんでした。


同様に


クラスCubeのメンバ関数である自作関数display内の


a

no

tate

yoko

takasa

main関数内でオブジェクト宣言された


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

cube1.a

cube1.no

cube1.tate

cube1.yoko

cube1.takasa

が代入されても


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

cube1.a

cube1.no

cube1.tate

cube1.yoko

cube1.takasa

から

a

no

tate

yoko

takasa

値渡しが行われるのみで


main関数内でオブジェクト宣言された


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

cube1.a

cube1.no

cube1.tate

cube1.yoko

cube1.takasa


に格納される数値は


1

0.0

0.0

0.0

0.0


のまま


変化していないかもしれないということなんです。」


マックス「げええ それはないだろう」


ソーラー「そのことを確かめるために



今のプログラムのmain関数内に


cout <<"cube1.aの値はほんとに" <<cube1.a<< "になりました" << "\n";

cout << "立方体につけられたナンバーはほんとに" << cube1.no << "になりました" << "\n";

cout << "立方体の縦の長さはほんとに" << cube1.tate << "になりました" << "\n";

cout << "立方体の横の長さはほんとに" << cube1.yoko << "になりました" << "\n";

cout << "立方体の高さの長さはほんとに" << cube1.takasa << "になりました" << "\n";


を加えたものを実行してみたいと思います。


#include <iostream>


using namespace std;


class Cube {


public:

int no;

public:

float tate;

public:

float yoko;

public:

float takasa;


public:

Cube();


/*🌞🌞🌞クラスCubeのコンストラクタCube() のメンバ関数宣言を行っています*/


public:

void display(); //自作関数display()のクラスCubeのメンバ関数宣言を行っています


public:

static int a;

/*🌞🌞🌞ここですよ~ん🌞🌞🌞

静的メンバ変数aのCubeのメンバ変数宣言を行っています*/


};


Cube::Cube() {


no = 0;

tate = 0;

yoko = 0;

takasa = 0;


cout << "生成されたオブジェクトのメンバ変数を初期化しました" << "\n";


}

/*👆🌞

クラスのコンストラクタCube()の定義を行っています

🌞*/



void Cube::display() {


cout << a << "回目のオブジェクトcube1のメンバ関数cube1.display()を実行しました" << "\n";


a++;

cout << "cube1.aの値は" << a << "になりました" << "\n";

no++;

cout << "立方体につけられたナンバーは" << no << "です" << "\n";

tate++;

cout << "立方体の縦の長さは" << tate << "です" << "\n";

yoko++;

cout << "立方体の横の長さは" << yoko << "です" << "\n";

takasa++;

cout << "立方体の高さの長さは" << takasa << "です" << "\n";


}


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


int Cube::a = 1;



//👆🌞🌞🌞ここです🌞🌞🌞静的メンバ変数aの初期化を行っています

//👆🌞🌞🌞静的メンバ変数aの格納する値は1になります



int main() {


Cube cube1;


//👆cube1のクラスCube型のオブジェクト宣言をおこなっています

/*🌞このとき オブジェクトcube1のコンストラクタが自動的に実行されています*/


cout << "オブジェクトcube1の静的メンバ変数cube1.aに代入された数値は" << cube1.a << "です" << "\n";


cube1.display();


cout << "cube1.aの値はほんとに" << cube1.a << "になりました" << "\n";

cout << "立方体につけられたナンバーはほんとに" << cube1.no << "になりました" << "\n";

cout << "立方体の縦の長さはほんとに" << cube1.tate << "になりました" << "\n";

cout << "立方体の横の長さはほんとに" << cube1.yoko << "になりました" << "\n";

cout << "立方体の高さの長さはほんとに" << cube1.takasa << "になりました" << "\n";



return 0;

}


プログラムの実行結果


生成されたオブジェクトのメンバ変数を初期化しました

オブジェクトcube1の静的メンバ変数cube1.aに代入された数値は1です

1回目のオブジェクトcube1のメンバ関数cube1.display()を実行しました

cube1.aの値は2になりました

立方体につけられたナンバーは1です

立方体の縦の長さは1です

立方体の横の長さは1です

立方体の高さの長さは1です

cube1.aの値はほんとに2になりました

立方体につけられたナンバーはほんとに1になりました

立方体の縦の長さはほんとに1になりました

立方体の横の長さはほんとに1になりました

立方体の高さの長さはほんとに1になりました


マックス「


ではなぜ


クラスCubeのメンバ関数である自作関数display()内の


a

no

tate

yoko

takasa

main関数内でオブジェクト宣言された


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

cube1.a

cube1.no

cube1.tate

cube1.yoko

cube1.takasa

が代入されているのに


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

cube1.a

cube1.no

cube1.tate

cube1.yoko

cube1.takasa

から

a

no

tate

yoko

takasa

データだけが渡される値渡しが行われるようなことはなく


main関数内でオブジェクト宣言された


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

cube1.a

cube1.no

cube1.tate

cube1.yoko

cube1.takasa


に格納されていた数値データは


クラスCubeのメンバ関数である自作関数display()の操作を受けて


1

0.0

0.0

0.0

0.0


から


2.0

1.0

1.0

1.0

1.0



変化したのか


ということだが・・・・・・


分からん😊


☆  ☆  ☆  ☆  ☆  ☆  ☆  ☆  ☆  ☆  ☆  ☆



このプログラムの場合



クラスCubeのメンバ関数である自作関数display()内の


a

no

tate

yoko

takasa

main関数内でオブジェクト宣言された


別の変数ともいえる


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

cube1.a

cube1.no

cube1.tate

cube1.yoko

cube1.takasa

          代入されているのではなく


クラスCubeのメンバ関数である自作関数display()内の


a

no

tate

yoko

takasa


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

cube1.a

cube1.no

cube1.tate

cube1.yoko

cube1.takasa

            

            💖そのもの💖



というわけなのですね。


ですので



cube1.a

cube1.no

cube1.tate

cube1.yoko

cube1.takasa


自作関数display()の操作を


受けて


cube1.a

cube1.no

cube1.tate

cube1.yoko

cube1.takasa

に格納される値は


1

0.0

0.0

0.0

0.0


から


2

1.0

1.0

1.0

1.0



変化するというわけです。




おまけの考察


クラスCubeのメンバ関数display()の定義

👇

void Cube::display() {


cout << a << "回目のオブジェクトcube1のメンバ関数display()を実行しました" << "\n";


a++;

cout << "cube1.aの値は" << a << "になりました" << "\n";

no++;

cout << "立方体につけられたナンバーは" << no << "です" << "\n";

tate++;

cout << "立方体の縦の長さは" << tate << "です" << "\n";

yoko++;

cout << "立方体の横の長さは" << yoko << "です" << "\n";

takasa++;

cout << "立方体の高さの長さは" << takasa << "です" << "\n";


}

👆

内で用いられている

クラスCubeのメンバ変数

a

no

tate

yoko

takasa



クラスCubeのメンバ関数display()の定義内で


変数宣言された変数ではなく


クラスCubeのメンバ関数display()の定義の外


Cubeのクラス宣言内で


変数宣言された変数です。


つまり


クラスCubeのメンバ変数

a

no

tate

yoko

takasa



自作関数である


display()内で変数宣言された


変数ではないので


自作関数display()内でのみ使用できる


変数ではないということです。


________________________________________________

通常


自作関数の定義内で変数宣言された変数は


自作関数内でのみ使用することができます。


自作関数の実行後は


自作関数の定義内で変数宣言された変数は


メモリから消去されることになります

________________________________________________


クラスCubeのメンバ変数

a

no

tate

yoko

takasa



Cubeのクラス宣言

👇

class Cube {


public:

int no;

public:

float tate;

public:

float yoko;

public:

float takasa;


public:

Cube();


/*🌞🌞🌞クラスCubeのコンストラクタCube() のメンバ関数宣言を行っています*/


public:

void display(); //自作関数display()のクラスCubeのメンバ関数宣言を行っています


public:

static int a;

/*🌞🌞🌞ここですよ~ん🌞🌞🌞

静的メンバ変数aのCubeのメンバ変数宣言を行っています*/


};

👆



に続く


クラスCubeのコンストラクタ

Cube()の定義内でも


クラスCubeのメンバ関数display()

の定義内でも使用され


main関数内の


オブジェクトcube1のメンバ関数


cube1.display()が実行されるとき


cube1.displayの定義内の


クラスCubeのメンバ変数

a

no

tate

yoko

takasa


cube1.a

cube1.no

cube1.tate

cube1.yoko

cube1.takasa

が代入されるという形で


使用されています。


Cubeのクラス宣言内で


public:

int no;

public:

float tate;

public:

float yoko;

public:

float takasa;


public:

static int a;


と変数宣言された




           💖クラスCubeのメンバ変数💖

a

no

tate

yoko

takasa




               💖💖💖まるで💖💖💖



            💖メンバ変数宣言された行以下に作用する💖



            💖グローバル変数のような働きをする💖



特殊な変数なのですね。




                    solarplexussより

☆  ☆  ☆  ☆  ☆  ☆  ☆  ☆  ☆  ☆  ☆  ☆


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

作者を応援しよう!

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

応援したユーザー

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

新規登録で充実の読書を

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

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

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