🌻天国にいけるC++言語入門🌻 進化し続けるオブジェクト指向プログラミング ver3.2307
親クラス*型のポインタ変数に子クラス型のオブジェクトのアドレスを代入した場合はポインタ変数にアロー演算子を用いて子クラス型のオブジェクトの(🌞子クラスのメンバ変数、メンバ関数🌞)にはアクセスできません
ても親クラス*型のポインタ変数は子クラス型のオブジェクトの(親クラスの)メンバ変数、メンバ関数にしかアクセスできません 子クラス型のオブジェクトの(親クラスのメンバ変数、メンバ関数)にアクセスできても
親クラス*型のポインタ変数に子クラス型のオブジェクトのアドレスを代入した場合はポインタ変数にアロー演算子を用いて子クラス型のオブジェクトの(🌞子クラスのメンバ変数、メンバ関数🌞)にはアクセスできません
ソーラー「
それでは😊
お待たせしました。
親クラス*型のポインタ変数に
子クラス型のオブジェクトのアドレスを代入した場合は
親クラス*型のポインタ変数にアロー演算子->を用いた
親クラス*型のポインタ変数->(子クラスに元から備わっている)メンバ変数
親クラス*型のポインタ変数->(子クラスに元から備わっている)メンバ関数
では
子クラス型のオブジェクトの(子クラスに元から備わっている)メンバ変数
子クラス型のオブジェクトの(子クラスに元から備わっている)メンバ関数
の管理しているメモリ領域にアクセスすることはできない、
子クラス型のオブジェクトのアドレスを代入された
親クラス*型のポインタ変数にアロー演算子->を用いた
親クラス*型のポインタ変数->(子クラスに元から備わっている)メンバ変数
親クラス*型のポインタ変数->(子クラスに元から備わっている)メンバ関数
は
子クラス型のオブジェクトの(子クラスに元から備わっている)メンバ変数
子クラス型のオブジェクトの(子クラスに元から備わっている)メンバ関数
としては機能しない
代わりにならない
ということについて
観察してみたいと思います」
マックス「ほ、ほえぇ なんのことぉ?
親クラス(アスタリスク)*型のポインタ変数に
子クラス型のオブジェクトのアドレスを代入するのか?
子クラス(アスタリスク)*型のポインタ変数に
子クラス型のオブジェクトのアドレスを代入するのではなく・・・?
代入するポインタ変数の型をまちがえてないか?」
ソーラー「そうなんです
子クラス型のオブジェクトのアドレスは
子クラス型のオブジェクトの(親クラスから引き継いだ)メンバ変数
子クラス型のオブジェクトの(親クラスから引き継いだ)メンバ関数
子クラス型のオブジェクトの(子クラスに元から備わっている)メンバ変数
子クラス型のオブジェクトの(子クラスに元から備わっている)メンバ関数
の管理しているメモリ領域を
管理している
代表しているアドレスなんです
このアドレスを格納することのできるポインタ変数は
子クラス(アスタリスク)*型のポインタ変数だけなんです
子クラス型のオブジェクトの(親クラスから引き継いだ)メンバ変数
子クラス型のオブジェクトの(親クラスから引き継いだ)メンバ関数
子クラス型のオブジェクトの(子クラスに元から備わっている)メンバ変数
子クラス型のオブジェクトの(子クラスに元から備わっている)メンバ関数
の管理しているメモリ領域を
管理している、
代表している
子クラス型のオブジェクトのアドレス
を
親クラス(アスタリスク)*型のポインタ変数に
代入するとどうなるか?ということですね
変数にはアドレスがあり
その変数のアドレスが代入されたポインタ変数
は
その変数の管理しているメモリ領域にアクセスすることができました
int型の変数のアドレスは
int*型のポインタ変数に
格納することができ
そのとき
int*型のポインタ変数を用いて
int型の変数の管理しているメモリ領域にアクセスすることができました
float*型の変数のアドレスは
float*型のポインタ変数に
格納することができ
そのとき
float*型のポインタ変数を用いて
float型の変数の管理しているメモリ領域にアクセスすることができました
同様に
子クラス型のオブジェクトは
変数であるので
子クラス型のオブジェクトにはアドレスがあり
そのアドレスを格納することができるのが
子クラス(アスタリスク)*型のポインタ変数なのです
子クラス(アスタリスク)*型のポインタ変数
を用いれば
子クラス型のオブジェクトの管理しているメモリ領域にアクセスすることができるというわけです
子クラス型のオブジェクトの管理しているメモリ領域
は
子クラス型のオブジェクトの(親クラスから引き継いだ)メンバ変数
子クラス型のオブジェクトの(親クラスから引き継いだ)メンバ関数
子クラス型のオブジェクトの(子クラスに元から備わっている)メンバ変数
子クラス型のオブジェクトの(子クラスに元から備わっている)メンバ関数
の管理しているメモリ領域なんです
ですので
子クラス(アスタリスク)*型のポインタ変数
は
子クラス型のオブジェクトの(親クラスから引き継いだ)メンバ変数
子クラス型のオブジェクトの(親クラスから引き継いだ)メンバ関数
子クラス型のオブジェクトの(子クラスに元から備わっている)メンバ変数
子クラス型のオブジェクトの(子クラスに元から備わっている)メンバ関数
の管理しているメモリ領域にアクセスすることができるというわけです
ただし
それは
子クラス(アスタリスク)*型のポインタ変数に
子クラス型のオブジェクトのアドレスを
代入した場合です
親クラス(アスタリスク)*型のポインタ変数に
子クラス型のオブジェクトのアドレスを
代入した場合は
親クラス*型のポインタ変数は
子クラス型のオブジェクトの(親クラスから引き継いだ)メンバ変数
子クラス型のオブジェクトの(親クラスから引き継いだ)メンバ関数
の管理しているメモリ領域にしかアクセスできなくなります
親クラス*型のポインタ変数は親クラス型オブジェクトの管理するメモリ領域にしかアクセスできない
親クラス型のオブジェクトの(親クラスに備わっている)メンバ変数
親クラス型のオブジェクトの(親クラスに備わっている)メンバ関数
にしかアクセスできない
それと似たような現象が起きています
親クラス*型のポインタ変数では
子クラス型のオブジェクトの(親クラスから引き継いだ)メンバ変数
子クラス型のオブジェクトの(親クラスから引き継いだ)メンバ関数
の管理しているメモリ領域にしか
アクセスできないのです
親クラス(アスタリスク)*型のポインタ変数に
子クラス型のオブジェクトのアドレスを
代入した場合
親クラス*型のポインタ変数にアロー演算子->を用いた
親クラス*型のポインタ変数->(親クラスから引き継いだ)メンバ変数
親クラス*型のポインタ変数->(親クラスから引き継いだ)メンバ関数
は
子クラス型のオブジェクトの(親クラスから引き継いだ)メンバ変数
子クラス型のオブジェクトの(親クラスから引き継いだ)メンバ関数
の管理しているメモリ領域にアクセスすることはできても
親クラス*型のポインタ変数にアロー演算子->を用いた
親クラス*型のポインタ変数->(子クラスに元から備わっている)メンバ変数
親クラス*型のポインタ変数->(子クラスに元から備わっている)メンバ関数
は
子クラス型のオブジェクトの(子クラスに元から備わっている)メンバ変数
子クラス型のオブジェクトの(子クラスに元から備わっている)メンバ関数
の管理しているメモリ領域にアクセスすることはできなくなります
ふ~ん
どうしようかな?
親クラス(アスタリスク)*型のポインタ変数に
子クラス型のオブジェクトのアドレスを代入すると
(正確ではありませんが)
親クラス(アスタリスク)*型のポインタ変数に
親クラス型のオブジェクトのアドレスを代入した
ことになる
って感じかな?
わかりやすいかな?
親クラス型のオブジェクトのアドレスが管理しているメモリ領域は
親クラス型のオブジェクトの(親クラスから引き継いだ)メンバ変数
親クラス型のオブジェクトの(親クラスから引き継いだ)メンバ関数
が管理しているメモリ領域だけです
親クラス型のオブジェクトの(子クラスに元から備わっている)メンバ変数
親クラス型のオブジェクトの(子クラスに元から備わっている)メンバ関数
は存在しないし
親クラス型のオブジェクトの(子クラスに元から備わっている)メンバ変数
親クラス型のオブジェクトの(子クラスに元から備わっている)メンバ関数
の管理しているメモリ領域は存在しません
つまり
親クラス(アスタリスク)*型のポインタ変数に
子クラス型のオブジェクトのアドレスを
代入した場合は
(まるで
親クラス(アスタリスク)*型のポインタ変数に
親クラス型のオブジェクトのアドレスを
代入したようになり)
親クラス*型のポインタ変数->(親クラスから引き継いだ)メンバ変数
親クラス*型のポインタ変数->(親クラスから引き継いだ)メンバ関数
は
子クラス型のオブジェクトの(親クラスから引き継いだ)メンバ変数
子クラス型のオブジェクトの(親クラスから引き継いだ)メンバ関数
が管理しているメモリ領域にアクセスすることはできても
子クラス型のオブジェクトの(子クラスに元から備わっている)メンバ変数
子クラス型のオブジェクトの(子クラスに元から備わっている)メンバ関数
の管理しているメモリ領域にアクセスすることはできなくなるというわけです
そのことを実際に観察してみようよ
まずは
親クラスGameCharacterのクラス宣言とそのメンバ関数statusDataDisplay()の定義を以下のように設定してみます
👇
class GameCharacter {
public:
string name;
int HP;
int MP;
void statusDataDisplay();
};
void GameCharacter::statusDataDisplay() {
cout << name << "\n";
cout << "HP " << HP << "\n";
cout << "MP " << MP << "\n";
cout << "親クラスのメンバ関数statusDataDisplay()が実行されました" << "\n";
}
親クラスGameCharacterを継承した
子クラスDragonとそのメンバ関数
statusDataDisplay2()の定義を以下のように設定してみます
class Dragon:public GameCharacter {
public:
int DP;//🌞ドラゴン型のキャラクター特有のドラゴンポイントが設定されています
void statusDataDisplay2();
};
void Dragon::statusDataDisplay2() {
cout << name << "\n";
cout << "HP " << HP << "\n";
cout << "MP " << MP << "\n";
cout << "DP " << DP << "\n";
cout << " 子クラスのメンバ関数が実行されました" << "\n";
}
ソーラー「
次に
💖親クラスGameCharacter*型💖のポインタ変数宣言
GameCharacter* pta;
によって作製された
💖親クラスGameCharacter*型のポインタ変数💖
pta
に
Pokkyの子クラスDragon型のオブジェクト宣言
Dragon Pokky;
によって作製された
🍋子クラスDragon型🍋のオブジェクトPokkyのアドレス
&Pokky
が
pta=&Pokky;
と
代入された状態で
💖親クラスGameCharacter*型のポインタ変数💖
pta
にアロー演算子を用いた
pta->に
子クラスDragonのメンバ変数DPが用いられた
pta->DP=10;
子クラスDragonのメンバ関数statusDataDisplay2()が用いられた
pta->statusDataDisplay2();
が実行できるかどうかを試してみたいと思います」
マックス「??
💖親クラスGameCharacter*型💖のポインタ変数宣言
GameCharacter* pta;
によって作製された
親クラスGameCharacter*型のポインタ変数
pta
に
Pokkyの子クラスDragon型のオブジェクト宣言
Dragon Pokky;
によって作製された
🍋子クラスDragon型🍋のオブジェクトPokkyのアドレス
&Pokky
が
pta=&Pokky;
と
代入された場合
(正確ではないが(´▽`*))
💖親クラスGameCharacter型💖のオブジェクトPokkyのアドレス
&Pokky
が
pta=&Pokky;
と
代入されたと捉えればいいんだろう
親クラスGameCharacter
と
親クラスGameCharacterを継承した子クラスDragon
の違いはというと
子クラスDragon
は
親クラスGameCharacter
の
メンバ変数宣言
メンバ関数宣言
を引き継いでいるが
親クラスGameCharacter
は
子クラスDragonだけに備わっている
メンバ変数宣言
メンバ関数宣言
を引き継いでいないということだ
まあ そりゃ そうだよな
子クラスDragonだけに備わっている
メンバ変数宣言
メンバ関数宣言
を
逆に
親クラスGameCharacterが
継承するはずもないか
う~ん
親クラスGameCharacter*型のポインタ変数
pta
に
💖親クラスGameCharacter型💖のオブジェクトPokkyのアドレス
&Pokky
が代入されたと見なすと
親クラスGameCharacter*型のポインタ変数
pta
に
子クラスDragonのメンバ変数DPが用いられた
pta->DP
は
使用できない
pta->DP=10;
を実行することはできない
もちろん
子クラスDragonのメンバ関数statusDataDisplay2()が用いられた
pta->statusDataDisplay2();
も実行できない
なぜなら
💖親クラスGameCharacter型💖のオブジェクトPokkyのアドレス
&Pokky
では
そもそも
アクセスできるメモリ領域が
子クラスDragon型のオブジェクトPokkyの(親クラスから引き継いだ)メンバ変数
Pokky.name
Pokky.HP
Pokky.MP
子クラスDragon型のオブジェクトPokkyの(親クラスから引き継いだ)メンバ関数
Pokky.tatusDataDisplay
の管理しているメモリ領域だけだからだ
Pokky.name
Pokky.HP
Pokky.MP
Pokky.statusDataDisplay
の管理しているメモリ領域
には
💖親クラスGameCharacter*型のポインタ変数💖
pta
にアロー演算子を用いた
pta->name
Pokky->HP
Pokky->MP
Pokky->statusDataDisplay
でアクセスすることができるが
子クラスDragon型のオブジェクトPokkyの(子クラスに元から備わっている)メンバ変数
Pokky.DP
子クラスDragon型のオブジェクトPokkyの(子クラスに元から備わっている)メンバ関数
Pokky.statusDataDisplay2()
の管理しているメモリ領域には
pta->DP
pta->statusDataDisplay
では
アクセスできないってわけだ
まあ
通常
💖親クラスGameCharacter(アスタリスク)*型のポインタ変数💖
には
💖親クラスGameCharacter型のオブジェクトのアドレスしか代入できない
んだからあ
それが効いているんだろう」
ソーラー「うげぇっ す、するどい・・・
😊🐱🚀🐱👓🐱🐉🐱💻🐱🏍🤳」
マックス「な、なんか 珍しい絵文字がでてるぞ
大丈夫か?」
ソーラー「それでは
あらためまして
💖親クラスGameCharacter*型💖のポインタ変数宣言
GameCharacter* pta;
によって作製された
💖親クラスGameCharacter*型のポインタ変数💖
pta
に
Pokkyの子クラスDragon型のオブジェクト宣言
Dragon Pokky;
によって作製された
🍋子クラスDragon型🍋のオブジェクトPokkyのアドレス
&Pokky
が
pta=&Pokky;
と
代入された状態で
子クラスDragonの(子クラスに元から備わっている)メンバ変数DPが用いられた
pta->DP=10;
子クラスDragonの(子クラスに元から備わっている)メンバ関数statusDataDisplay2()が用いられた
pta->statusDataDisplay2();
が
実行できるかどうかを試してみたいと思います
そのプログラムはこちらです
👇
#include <iostream>
#include <string>//文字列を取り扱うためにヘッダファイル <string>をインクルードしています
using namespace std;
class GameCharacter {
public:
string name;
int HP;
int MP;
void statusDataDisplay();
};
void GameCharacter::statusDataDisplay() {
cout << name << "\n";
cout << "HP " << HP << "\n";
cout << "MP " << MP << "\n";
cout << "親クラスのメンバ関数statusDataDisplay()が実行されました" << "\n";
}
class Dragon :public GameCharacter {
public:
int DP;
void statusDataDisplay2();
};
void Dragon::statusDataDisplay2() {
cout << name << "\n";
cout << "HP " << HP << "\n";
cout << "MP " << MP << "\n";
cout << "DP " << DP << "\n";
cout << " 子クラスのメンバ関数statusDataDisplay2()が実行されました" << "\n";
}
int main() {
Dragon Pokky;
//👆Pokkyの子クラスDragon型のオブジェクト宣言をおこなっています
GameCharacter* pta;
pta = &Pokky;
pta->name = "ポッキー";
pta->HP = 15;
pta->MP = 5;
pta->DP = 7;
pta->statusDataDisplay();
pta->statusDataDisplay2();
return 0;
}
ソーラー「さあっ ほっかほかのビルド実行結果は・・・
いかに!」
ビルド実行結果
エラー (アクティブ) E0135 class "GameCharacter" にメンバー "statusDataDisplay2" がありません
エラー (アクティブ) E0135 class "GameCharacter" にメンバー "DP" がありません
エラー C2039 'statusDataDisplay2': 'GameCharacter' のメンバーではありません。
エラー C2039 'DP': 'GameCharacter' のメンバーではありません。
ソーラー「出てきました😊
エラー (アクティブ) E0135 class "GameCharacter" にメンバー "statusDataDisplay2" がありません
エラー (アクティブ) E0135 class "GameCharacter" にメンバー "DP" がありません
エラー C2039 'statusDataDisplay2': 'GameCharacter' のメンバーではありません。
エラー C2039 'DP': 'GameCharacter' のメンバーではありません。
ソーラー「
pta->DP = 7;
pta->statusDataDisplay2();
を実行しようとしているから
このエラーが表示されたんだね
💖親クラスGameCharacter*型💖のポインタ変数宣言
GameCharacter* pta;
によって作製された
親クラスGameCharacter*型のポインタ変数
pta
に
Pokkyの子クラスDragon型のオブジェクト宣言
Dragon Pokky;
によって作製された
🍋子クラスDragon型🍋のオブジェクトPokkyのアドレス
&Pokky
が
pta=&Pokky;
と
代入された場合は
(正確ではないものの)
単に
親クラスGameCharacter*型のポインタ変数
pta
に
💖親クラスGameCharacter型💖のオブジェクトPokkyのアドレス
&Pokky
が
pta=&Pokky;
と
代入されたととらえるとわかりやすいんだね
単に
親クラスGameCharacter*型のポインタ変数
pta
に
💖親クラスGameCharacter型💖のオブジェクトPokkyのアドレス
&Pokky
が
代入されたなら
親クラスGameCharacterのクラス宣言内には
メンバ変数宣言
string name;
int HP;
int MP;
メンバ関数宣言
void statusDataDisplay();
は設定されていても
メンバ変数宣言
int DP;
メンバ関数宣言
void statusDataDisplay2();
は設定されていないので
親クラスGameCharacter*型のポインタ変数
pta
に
アロー演算子を用いた
pta->name
pta->HP
pta->MP
pta->statusDataDisplay()
しか
存在できないことになるよね
となると
pta->name = "ポッキー";
pta->HP = 15;
pta->MP = 5;
pta->statusDataDisplay();
は実行できても
もちろん
pta->DP = 7;
pta->statusDataDisplay2();
を実行することはできないってことになるんだ」
新規登録で充実の読書を
- マイページ
- 読書の状況から作品を自動で分類して簡単に管理できる
- 小説の未読話数がひと目でわかり前回の続きから読める
- フォローしたユーザーの活動を追える
- 通知
- 小説の更新や作者の新作の情報を受け取れる
- 閲覧履歴
- 以前読んだ小説が一覧で見つけやすい
アカウントをお持ちの方はログイン
ビューワー設定
文字サイズ
背景色
フォント
組み方向
機能をオンにすると、画面の下部をタップする度に自動的にスクロールして読み進められます。
応援すると応援コメントも書けます