🌻天国にいけるC++言語入門🌻 進化し続けるオブジェクト指向プログラミング ver3.2307
thisはポインタ変数なのでthisにオブジェクトp1のアドレスが代入されるとthis->x,this->yはp1.x,p1.yのアクセスしているメモリに直接アクセスすることになります
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つのクラスは
全く同じ構造なんだね💖
🌞 🌞 🌞 🌞 🌞 🌞 🌞 🌞 🌞
新規登録で充実の読書を
- マイページ
- 読書の状況から作品を自動で分類して簡単に管理できる
- 小説の未読話数がひと目でわかり前回の続きから読める
- フォローしたユーザーの活動を追える
- 通知
- 小説の更新や作者の新作の情報を受け取れる
- 閲覧履歴
- 以前読んだ小説が一覧で見つけやすい
アカウントをお持ちの方はログイン
ビューワー設定
文字サイズ
背景色
フォント
組み方向
機能をオンにすると、画面の下部をタップする度に自動的にスクロールして読み進められます。
応援すると応援コメントも書けます