thisはポインタ変数なのでthisにオブジェクトp1のアドレスが代入されるとthis->x,this->yはp1.x,p1.yのアクセスしているメモリに直接アクセスすることになります

🌞   🌞   🌞   🌞   🌞   🌞   🌞   🌞   🌞



       次のプログラムをちょっとみてみて

👇


#include <iostream>


using namespace std;


class Point{


public: //アクセス指定子がpublicに設定されています

int x;

int y;


public:


void pointdisplay();


};


void Point::pointdisplay() {


this->x = 2;

this->y = 2;


cout << this->x << "\n";

cout << this->y << "\n";

}


int main() {


Point p1;


p1.x = 1;

p1.y = 1;


p1.pointdisplay();


return 0;

}


ビルド実行結果


2

2


このプログラムでは


p1のクラスPoint型のオブジェクト宣言


Point p1;


p1.x=1;

p1.y=1;


により


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


p1.x

p1.y


には


1

1


が代入されています


次に


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


p1.pointdisplay();


が実行されています


つまり


クラスPointのメンバ関数pointdisplay()の定義

👇

void Point::pointdisplay() {


this->x=2;

this->y=2;


cout <<this->x << "\n";

cout <<this->y << "\n";

}



this->x=2;

this->y=2;


cout <<this->x << "\n";

cout <<this->y << "\n";


のポインタ変数thisに


クラスPoint型のオブジェクトp1のアドレス&p1が代入されたもの



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


このとき


this->x

this->y



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


p1.x

p1.y


のアクセスしているメモリにアクセスすることになります


つまり


this->x

this->y



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


p1.x

p1.y


を表すことになるので



this->x=2;

this->y=2;


が実行されると


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


p1.x

p1.y


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


1

1

から

2

2


に変化します


p1.pointdisplay();


のビルド実行結果が


2

2


になるというわけです



🌞   🌞   🌞   🌞   🌞   🌞   🌞   🌞   🌞




マックス「この


クラスPointのメンバ関数pointdisplay()の定義

👇

void Point::pointdisplay() {


this->x=2;

this->y=2;


cout <<this->x << "\n";

cout <<this->y << "\n";

}


でポインタ変数thisが用いられているが


別に


ポインタ変数thisを用いなくても


クラスPointのメンバ関数pointdisplay()の定義は

👇

void Point::pointdisplay() {


x=2;

y=2;


cout <<x << "\n";

cout <<y << "\n";

}


でいいんじゃないか」


ソーラー「そういえば・・・そうですね。


クラスPointのメンバ関数pointdisplay()の定義が

👇

void Point::pointdisplay() {


x=2;

y=2;


cout <<x << "\n";

cout <<y << "\n";

}


のときでも


p1.pointdisplay();


が実行される際


x=2;

y=2;


cout <<x << "\n";

cout <<y << "\n";



xにp1.x

yにp1.y


が代入された


p1.x=2;

p1.y=2;


cout << p1.x << "\n";

cout << p1.y << "\n";


が実行されるので


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


p1.x

p1.y


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


1

1

から

2

2


に変化します


じゃあthisはいらないってことなのかな?」


マックス「確かにthisはいらないことになるが・・・


う~ん・・?」


てんC「マックスさん


先ほどのプログラム

👇



#include <iostream>


using namespace std;


class Point{


public: //アクセス指定子がpublicに設定されています

int x;

int y;


public:


void pointdisplay();


};


void Point::pointdisplay() {


this->x=2;

this->y=2;


cout <<this->x << "\n";

cout <<this->y << "\n";

}


int main(){


Point p1;


p1.x=1;

p1.y=1;


p1.pointdisplay();


return 0;

}


ビルド実行結果


2

2



次のプログラムのように書き換えることができるのではないですか?

👇

#include <iostream>


using namespace std;


class Point{


public: //アクセス指定子がpublicに設定されています

int x;

int y;


public:


void pointdisplay(Point* a);


};


void Point::pointdisplay(Point* a) {


a->x=2;

a->y=2;


cout <<a->x << "\n";

cout <<a->y << "\n";

}


int main(){


Point p1;


p1.x=1;

p1.y=1;


p1.pointdisplay(&p1);


return 0;

}


ビルド実行結果


2

2


ソーラー「


このプログラムも


ビルド実行結果が


2

2



なっているね


このプログラムでは何が行われているのかな」


てんC「はい このプログラムでは


まず


先ほどのプログラムの


クラスPointのメンバ関数宣言を


void pointdisplay();


から


void pointdisplay(Point* a);


に変更し


クラスPointのメンバ関数の定義を


void Point::pointdisplay() {


this->x=2;

this->y=2;


cout <<this->x << "\n";

cout <<this->y << "\n";

}


から


void Point::pointdisplay(Point* a) {


a->x=2;

a->y=2;


cout <<a->x << "\n";

cout <<a->y << "\n";

}


に設定し直しました


では


このように


クラスPointのメンバ関数宣言

クラスPointのメンバ関数の定義


が変更された状態の


プログラムがどのように実行されるかを見ていきます


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

👇

#include <iostream>


using namespace std;


class Point{


public: //アクセス指定子がpublicに設定されています

int x;

int y;


public:


void pointdisplay(Point* a);


};


void Point::pointdisplay(Point* a) {


a->x = 2;

a->y = 2;


cout << a->x << "\n";

cout << a->y << "\n";

}


int main() {


Point p1;


p1.x = 1;

p1.y = 1;


p1.pointdisplay(&p1);


return 0;

}


ビルド実行結果

2

2



てんC「このプログラムでは


まず


p1のクラスPoint型のオブジェクト宣言


Point p1;


により


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


p1.x

p1.y


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


p1.pointdisplay(Point* a)


が生成されています


そして


p1.x=1;

p1.y=1;


により


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


p1.x

p1.y



数値データ


1

1


が代入されています


そして


いよいよ


p1.pointdisplay(Point* a)

&p1が代入された


p1.pointdisplay(&p1);


の実行ですね。


p1.pointdisplay(&p1);


では


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


p1.pointdisplay(Point* a)

Point* a


クラスPoint型のオブジェクトp1のアドレス&p1が代入されたものが実行されることになります


つまり


クラスPointのメンバ関数pointdisplay(Point* a)の定義

👇

void Point::pointdisplay(Point* a) {


a->x=2;

a->y=2;


cout <<a->x << "\n";

cout <<a->y << "\n";

}



Point* aに


クラスPoint型のオブジェクトp1のアドレス&p1が代入された


状態の


a->x=2;

a->y=2;


cout <<a->x << "\n";

cout <<a->y << "\n";



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


クラスPoint*型のポインタ変数aには


クラスPoint型のオブジェクトp1のアドレス&p1が代入されているので


a->x

a->y



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


p1.x

p1.y


をあらわすことになります


ですので


a->x=2;

a->y=2;


cout <<a->x << "\n";

cout <<a->y << "\n";


が実行されるということは


p1.x=2;

p1.y=2;


cout <<p1.x << "\n";

cout <<p1.y << "\n";


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


ですから


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


p1.x

p1.y



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


1

1

から

2

2


に変化し


コマンドプロンプト画面に


2

2


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



🌞   🌞   🌞   🌞   🌞   🌞   🌞   🌞   🌞


すっご~い わあ  なるほど  


そうだ そうなるよね 


🌞   🌞   🌞   🌞   🌞   🌞   🌞   🌞   🌞




てんC「


今のプログラムでは


自作関数であるクラスPointのメンバ関数pointdisplay(Point* a)


の引数となっているPoint* a


つまりクラスPoint*型のポインタ変数aに


クラスPoint型のオブジェクトp1のアドレス&p1を代入する



            参照渡し(ポインタ渡し)


が行われています



このように自作関数の引数となっているポインタ変数に


main関数内で定義された変数のアドレスを代入することを


参照渡し(ポインタ渡し)というのでしたね


ここで


このプログラムの


ポインタ変数名を


aからthisに変更したものは


ポインタ変数名を変更しただけですが


実行することができません


そのプログラムは次のようになります


#include <iostream>


using namespace std;


class Point{


public: //アクセス指定子がpublicに設定されています

int x;

int y;


public:


void pointdisplay(Point* this);


};


void Point::pointdisplay(Point* this) {


this->x = 2;

this->y = 2;


cout << this->x << "\n";

cout << this->y << "\n";

}


int main() {


Point p1;


p1.x = 1;

p1.y = 1;


p1.pointdisplay(&p1);


return 0;

}



ビルド実行結果



エラー C2059 構文エラー: 'this'

エラー C2059 構文エラー: 'this'

エラー C2143 構文エラー: ';' が '{' の前にありません。

エラー C2143 構文エラー: ';' が 'this' の前にありません。

エラー C2143 構文エラー: ';' が 'this' の前にありません。

エラー C2143 構文エラー: ')' が 'this' の前にありません。

エラー C2143 構文エラー: ')' が 'this' の前にありません。

エラー C2059 構文エラー: ')'

エラー C2059 構文エラー: ')'

エラー C2447 '{': 対応する関数ヘッダーがありません (旧形式の仮引数リスト?)

エラー C2761 'void Point::pointdisplay(Point *)': メンバーの再宣言はできません

エラー C2238 ';' の前に無効なトークンがあります。

エラー (アクティブ) E0018 ')' が必要です

エラー (アクティブ) E0018 ')' が必要です


てんC「


このプログラムを実行すると


自作関数であるクラスPointのメンバ関数pointdisplay(Point* this)


の引数となっているPoint* this


つまりクラスPoint*型のポインタ変数thisに


クラスPoint型のオブジェクトp1のアドレス&p1を代入する



           参照渡し(ポインタ渡し)


が行われることになるはずなのですが


ビルドエラーが表示されることになります


このような


ポインタ変数thisを


クラスのメンバ関数の引数にもちいるような使い方は間違っているというわけです


ここで


クラスPointのメンバ関数宣言


void pointdisplay(Point* this);



クラスPointのメンバ関数の定義

👇

void Point::pointdisplay(Point* this) {


this->x = 2;

this->y = 2;


cout << this->x << "\n";

cout << this->y << "\n";

}



Point* this


を取り除けば


プログラムを実行できるようになります。


それが


このエピソードの最初のプログラムなんです

👇

#include <iostream>


using namespace std;


class Point{


public: //アクセス指定子がpublicに設定されています

int x;

int y;


public:


void pointdisplay();


};


void Point::pointdisplay() {


this->x=2;

this->y=2;


cout <<this->x << "\n";

cout <<this->y << "\n";

}


int main(){


Point p1;


p1.x=1;

p1.y=1;


p1.pointdisplay();


return 0;

}


ビルド実行結果


2

2


てんC「本来


クラスPointのメンバ関数宣言


void pointdisplay(Point* this);



クラスPointのメンバ関数の定義


void Point::pointdisplay(Point* this) {


this->x = 2;

this->y = 2;


cout << this->x << "\n";

cout << this->y << "\n";

}


が設定されている場合でも


Point p1;


p1.x=1;

p1.y=1;


p1.pointdisplay();


の実行時


クラスPoint*型のポインタ変数thisに


クラスPoint型のオブジェクトp1のアドレス&p1を代入する



            参照渡し(ポインタ渡し)


がおこなわれてもいいはずなのですが


プログラムの実行はできません。


しかし実行できたなら


Point p1;


p1.x=1;

p1.y=1;


p1.pointdisplay();


の実行時


Point*型のポインタ変数thisに


オブジェクトp1のアドレス&p1を代入する



            参照渡し(ポインタ渡し)


がおこなわれるはずです。


ということは



          なんとなく



クラスPointのメンバ関数宣言


void pointdisplay(Point* this);



クラスPointのメンバ関数の定義


void Point::pointdisplay(Point* this) {


this->x = 2;

this->y = 2;


cout << this->x << "\n";

cout << this->y << "\n";

}



Point* thisの部分


を取り除いただけの


このエピソードの最初のプログラムの

👇

クラスPointのメンバ関数宣言


void pointdisplay();



クラスPointのメンバ関数の定義


void Point::pointdisplay() {


this->x = 2;//🌞thisは残っています

this->y = 2;//🌞thisは残っています


cout << this->x << "\n";

cout << this->y << "\n";

}



Point* this


を取り除いたので


ポインタ変数thisに自由にPoint型のオブジェクトのアドレスを


代入することができなくなるのですが


Point p1;


p1.x=1;

p1.y=1;


p1.pointdisplay();


の実行時


        なんとな~く


Point*型のポインタ変数thisに


クラスPoint型のオブジェクトp1のアドレス&p1を代入する



            参照渡し(ポインタ渡し)


が行われると推測されます」



🌞   🌞   🌞   🌞   🌞   🌞   🌞   🌞   🌞


     そう


クラスPointのメンバ関数宣言が


void pointdisplay();



クラスPointのメンバ関数の定義が


void Point::pointdisplay() {


this->x = 2;

this->y = 2;


cout << this->x << "\n";

cout << this->y << "\n";

}


に設定されている今のプログラムでも


表面上は分かりにくいのだけど


クラスPoint型のオブジェクトp1のアドレス&p1が


ポインタ変数thisに渡される


   参照渡し(ポインタ渡し)が行われています


そうして


this->x

this->y



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


p1.x

p1.y


をあらわすことになるのですね


クラスPoint型のオブジェクトp1のアドレス&p1が


ポインタ変数thisに渡される


   参照渡し(ポインタ渡し)が行われている


ということは


コンピューターが


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


p1.x

p1.y


にアクセスすることができるように


💖コンピューターにクラスPoint型のオブジェクトp1のアドレス&p1を教えている💖


ということなのですが



実は今まで慣れ親しんできた


クラスPointのメンバ関数宣言が


void pointdisplay();



クラスPointのメンバ関数pointdisplay()の定義が


void Point::pointdisplay() {


x=2;

y=2;


cout <<x<< "\n";

cout <<y<< "\n";

}


の場合も


Point p1;


p1.x=1;

p1.y=1;


そして


p1.pointdisplay();

👆

が実行されるとき


コンピューターが


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


p1.x

p1.y


にアクセスできるよう


クラスPoint型のオブジェクトp1のアドレス&p1を


コンピュータに教える構造になっています


そのプログラムを観察してみましょう


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

👇

#include <iostream>


using namespace std;


class Point{


public: //アクセス指定子がpublicに設定されています

int x;

int y;


public:


void pointdisplay();


};


void Point::pointdisplay() {


x=2;

y=2;


cout <<x<< "\n";

cout <<y<< "\n";

}


int main(){


Point p1;


p1.x=1;

p1.y=1;


p1.pointdisplay();


return 0;

}


ビルド実行結果


2

2


🌞   🌞   🌞   🌞   🌞   🌞   🌞   🌞   🌞




てんC「このプログラムでは


p1のクラスPoint型のオブジェクト宣言


Point p1;


により


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


p1.x

p1.y


が生成され


p1.x=1;

p1.y=1;


の実行により


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


p1.x

p1.y


数値データ

1

1


が代入されています


そして


p1.pointdisplay();


が実行されると


クラスPointのメンバ関数pointdisplay()の定義

👇

void Point::pointdisplay() {


x=2;

y=2;


cout <<x<< "\n";

cout <<y<< "\n";

}



xにp1.x

yにp1.y


が代入された


p1.x=2;

p1.y=2;


cout <<p1.x<< "\n";

cout <<p1.y<< "\n";



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


ですので


コマンドプロンプト画面に


2

2


が表示されます」


マックス「??


このプログラムでは


p1.pointdisplay();

👆

が実行されても


クラスPoint型のオブジェクトp1のアドレス&p1が


クラスPointのメンバ関数


pointdisplay()


の引数となっているポインタ変数に


ポインタ渡しされていないようにみえるが・・・


そもそも


クラスPointのメンバ関数


pointdisplay()


は引数にオブジェクトp1のアドレス&p1をポインタ渡しできるような


クラスPoint*型のポインタ変数宣言


Point* a


のようなものが


設定されていない・・・」



🌞   🌞   🌞   🌞   🌞   🌞   🌞   🌞   🌞



            そう


           一見すると


p1.pointdisplay();

👆

が実行されても


クラスPoint型のオブジェクトp1のアドレス&p1が


クラスPointのメンバ関数の引数となっているポインタ変数に


ポインタ渡しされていないようにみえます



このプログラムでは


クラスPointのメンバ関数宣言が


void pointdisplay();


クラスPointのメンバ関数pointdisplay()の定義が

👇

void Point::pointdisplay() {


x=2;

y=2;


cout <<x<< "\n";

cout <<y<< "\n";

}


となっていますが


実は


クラスPointのメンバ関数宣言が


void pointdisplay();


クラスPointのメンバ関数pointdisplay()の定義が


void Point::pointdisplay() {


this->x=2;

this->y=2;


cout <<this->x<< "\n";

cout <<this->y<< "\n";

}


となっている状態の


this->


が省かれたものに相当するんです


ですから本来は


p1.pointdisplay();


が実行されるとき


ポインタ変数thisにオブジェクトp1のアドレス&p1


が代入された


this->x=2;

this->y=2;


cout <<this->x<< "\n";

cout <<this->y<< "\n";


に相当するものが実行されることになります


ポインタ変数thisにオブジェクトp1のアドレス&p1


を代入するポインタ渡しがおこなわれているというわけです


この時も


コンピュータが


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


p1.x

p1.y


にアクセスできるよう


コンピュータに


オブジェクトp1のアドレス&p1を教えているというわけです


ですので


p1.pointdisplay();


が実行されるとき



this->x

this->y



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


p1.x

p1.y


のアクセスしているメモリにアクセスすることになり


this->x

this->y



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


p1.x

p1.y


をあらわすことになります


ですから


最終的には


p1.pointdisplay();


が実行されるとき


ポインタ変数thisにオブジェクトp1のアドレス&p1が代入された


this->x=2;

this->y=2;


cout <<this->x<< "\n";

cout <<this->y<< "\n";


が実行されることに


イコール


p1.x=2;

p1.y=2;


cout <<p1.x<< "\n";

cout <<p1.y<< "\n";


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



ですので


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


p1.x

p1.y


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


1

1


から

2

2

変化することになります。



つまり


今まで慣れ親しんできたオーソドックスな


クラスPointのメンバ関数宣言が


void pointdisplay();


クラスPointのメンバ関数pointdisplay()の定義が

👇

void Point::pointdisplay() {


x=2;

y=2;


cout <<x<< "\n";

cout <<y<< "\n";

}


となっている場合でも


p1.pointdisplay();


が実行されるとき


       参照渡し(ポインタ渡し)


が行われて


コンピューターにオブジェクトp1のアドレスを教えているんです


そういえば


クラスPointのメンバ関数宣言が


void pointdisplay(Point* a);



クラスPointのメンバ関数の定義が


void Point::pointdisplay(Point* a) {


a->x=2;

a->y=2;


cout <<a->x << "\n";

cout <<a->y << "\n";

}


のとき


p1.pointdisplay(&p1);


が実行されると


クラスPoint型のオブジェクトp1のアドレス&p1が


クラスPointのメンバ関数の引数となっているポインタ変数aに


ポインタ渡しされていたね


今までのことをまとめると


今まで慣れ親しんできたオーソドックスな


クラスPointのメンバ関数宣言が


void pointdisplay();


クラスPointのメンバ関数pointdisplay()の定義が

👇

void Point::pointdisplay() {


x=2;

y=2;


cout <<x<< "\n";

cout <<y<< "\n";

}


となっている場合も


クラスPointのメンバ関数宣言が


void pointdisplay(Point* a);



クラスPointのメンバ関数の定義が


void Point::pointdisplay(Point* a) {


a->x=2;

a->y=2;


cout <<a->x << "\n";

cout <<a->y << "\n";

}


の場合も


クラスPoint のメンバ関数宣言が


void pointdisplay();



クラスPoint のメンバ関数の定義が


void Point::pointdisplay() {


this->x = 2;

this->y = 2;


cout << this->x << "\n";

cout << this->y << "\n";

}


の場合も


それぞれ


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

p1.pointdisplay();

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

p1.pointdisplay(&p1);

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

p1.pointdisplay();


が実行される際



   💖コンピューターにクラスPoint型のオブジェクトp1のアドレスを教えることで💖


コンピューターは


クラスPoint型のオブジェクトp1のアドレス&p1のメモリに


アクセスすることができるようになるんだね。


クラスPoint型のオブジェクトp1のアドレス&p1をコンピュータに教えるという点では


上記の3つのクラスは


全く同じ構造なんだね💖




🌞   🌞   🌞   🌞   🌞   🌞   🌞   🌞   🌞
















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

作者を応援しよう!

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

応援したユーザー

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

新規登録で充実の読書を

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

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

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