ても親クラス*型のポインタ変数は子クラス型のオブジェクトの(親クラスの)メンバ変数、メンバ関数にしかアクセスできません 子クラス型のオブジェクトの(親クラスのメンバ変数、メンバ関数)にアクセスできても

親クラス*型のポインタ変数に子クラス型のオブジェクトのアドレスを代入した場合はポインタ変数にアロー演算子を用いて子クラス型のオブジェクトの(🌞子クラスのメンバ変数、メンバ関数🌞)にはアクセスできません

ソーラー「


それでは😊


お待たせしました。


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



子クラス型のオブジェクトのアドレスを代入した場合は


親クラス*型のポインタ変数にアロー演算子->を用いた


親クラス*型のポインタ変数->(子クラスに元から備わっている)メンバ変数

親クラス*型のポインタ変数->(子クラスに元から備わっている)メンバ関数


では


子クラス型のオブジェクトの(子クラスに元から備わっている)メンバ変数

子クラス型のオブジェクトの(子クラスに元から備わっている)メンバ関数


の管理しているメモリ領域にアクセスすることはできない、


子クラス型のオブジェクトのアドレスを代入された


親クラス*型のポインタ変数にアロー演算子->を用いた


親クラス*型のポインタ変数->(子クラスに元から備わっている)メンバ変数

親クラス*型のポインタ変数->(子クラスに元から備わっている)メンバ関数



子クラス型のオブジェクトの(子クラスに元から備わっている)メンバ変数

子クラス型のオブジェクトの(子クラスに元から備わっている)メンバ関数


としては機能しない


代わりにならない


ということについて


観察してみたいと思います」



マックス「ほ、ほえぇ なんのことぉ?


親クラス(アスタリスク)*型のポインタ変数に


子クラス型のオブジェクトのアドレスを代入するのか?


子クラス(アスタリスク)*型のポインタ変数に


子クラス型のオブジェクトのアドレスを代入するのではなく・・・?


代入するポインタ変数の型をまちがえてないか?」


ソーラー「そうなんです



子クラス型のオブジェクトのアドレスは


子クラス型のオブジェクトの(親クラスから引き継いだ)メンバ変数

子クラス型のオブジェクトの(親クラスから引き継いだ)メンバ関数


子クラス型のオブジェクトの(子クラスに元から備わっている)メンバ変数

子クラス型のオブジェクトの(子クラスに元から備わっている)メンバ関数


の管理しているメモリ領域を


管理している


代表しているアドレスなんです


このアドレスを格納することのできるポインタ変数は



子クラス(アスタリスク)*型のポインタ変数だけなんです



子クラス型のオブジェクトの(親クラスから引き継いだ)メンバ変数

子クラス型のオブジェクトの(親クラスから引き継いだ)メンバ関数


子クラス型のオブジェクトの(子クラスに元から備わっている)メンバ変数

子クラス型のオブジェクトの(子クラスに元から備わっている)メンバ関数


の管理しているメモリ領域を


管理している、


代表している


子クラス型のオブジェクトのアドレス



親クラス(アスタリスク)*型のポインタ変数に


代入するとどうなるか?ということですね





変数にはアドレスがあり


その変数のアドレスが代入されたポインタ変数



その変数の管理しているメモリ領域にアクセスすることができました


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();


を実行することはできないってことになるんだ」

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

作者を応援しよう!

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

応援したユーザー

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

新規登録で充実の読書を

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

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

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