(新・ゲームプログラミングの館sp6章)thisポインタの意味について理解できないので誰かご教授ください。

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら

トピックに返信する


答えを正確にご入力ください。答えられるかどうかでスパムボットか否かを判定します。

BBCode: ON
[img]: ON
[flash]: OFF
[url]: ON
スマイリー: OFF

トピックのレビュー
   

展開ビュー トピックのレビュー: (新・ゲームプログラミングの館sp6章)thisポインタの意味について理解できないので誰かご教授ください。

Re: (新・ゲームプログラミングの館sp6章)thisポインタの意味について理解できないので誰かご教授ください。

#5

by 神田空田 » 5年前

今回の解説のおかげでインターフェースの理解ができ、シングルトンからの卒業ができそうです。

丁寧で詳しい解説、ありがとうございます。これからもよろしくお願いします!

Re: (新・ゲームプログラミングの館sp6章)thisポインタの意味について理解できないので誰かご教授ください。

#4

by Dixq (管理人) » 5年前

その記事を書いた者です。
#3の理解であっています。
必要な権限は最小限にして渡してやるというのが基本です。
今は小規模なプログラムだからいいでしょうが、
もしバグが起きた時、モジュールが100個あって、100個がグローバル変数を通してすべてにアクセスできるような設計だった場合
(そして、10人で作っていて自分は10モジュールしか把握していない場合)
さっぱりどこにバグがあるのか分かりません。
#変数の値がどういう時にどう変わっていくのかを追っていくのも困難です。
しかし、1モジュールにしかバグが生じた時の操作の権限が無ければそこだとわかります。
あらゆることがあらゆるところから操作可能なコードはスパゲティコードになって破綻してしまいます。

そこで、インターフェイスという概念が出てきます。
C++は言語的に未成熟な時にできたものですから、インターフェイスという言語上の仕組みがありません。
JavaやKotlin、Swiftなどのモダンな言語だとサポートしているのですが。
そこで、C++でモダンな言語の仕組みを似せて実装するために、
インターフェイスクラスというものを作って設計するのです。

Re: (新・ゲームプログラミングの館sp6章)thisポインタの意味について理解できないので誰かご教授ください。

#3

by 神田空田 » 5年前

この一文のおかげで解決しました。

「SceneMgrのインスタンス内のeSceneを操作する必要があります」

まず僕は、インターフェースについての理解が浅かったです。

//////////////////////// ここからは僕が理解した事を書きます //////////////////////

そもそも今回の目的は、

SceneMgr内のシーン切り替えをGame・Menu・Configで行いたいが、SceneMgrのインスタンス直接を持たせたくない

という事でしたね。そして、今回はSceneMgrとGame・Menu・ConfigとでインターフェースであるISceneChangerを持たせることでこれを実現します。(インスタンスを持たせるという考え方は変わらない、間接的に持たせる考え方をする。)

ここで注意しないといけないのが(よく考えると当たり前なのですが。。。)実際に操作したいのはSceneMgr型のインスタンス(main関数内の”mgr”)が持つeSceneという変数である事。

そして、mgrはSceneMgr型であるので、ChangeScene関数を持つので、BaseSceneへmgrを渡してやればよいと考えるが、それでは、BaseSceneが何でもできてしまう。(題意に反する)
そこで、BaseSceneへmgrを渡すときに、”型をISceneChanger”(ChangeScene関数しか使えない型)に指定する事で、めでたくBaseSceneはmgrの持つ機能のうちのChangeScene関数のみしか使えなくなる。
これを実現するためにも、SceneMgrにはISceneChangerを継承しておく。(後でISceneChanger型インスタンスmSceneChangerにSceneMgr型インスタンスmgrを入れるため)

という事ですね。

別の言い方でいうと、

BaseScene は ISceneChanger というフィルタ(ChangeScene関数しか使えない)を通して mgr に操作を与えている。

という事ですね。
もしよろしければですが、この解釈が正しいかもお答えしていただくとうれしいです。
それに、非常に的確な回答だったと思います。理解が非常に進みました。

Re: (新・ゲームプログラミングの館sp6章)thisポインタの意味について理解できないので誰かご教授ください。

#2

by にほ » 5年前

私の拙い解釈で回答させていただきます。
このthisポインタは、最終的にmSceneChanger(BaseScene.hで定義したISceneChangerポインタ型変数)に代入されるのでしょうが、わざわざ、mSceneChangerへのthisポインタ渡しの操作をしなくてもいい気がしてしまいます。
mSceneChangerへポインタを渡さずにシーンを変更するということでしょうか?どういったコードで実装しようと考えているか知りたいですね。

と、書かれていますが、なぜ「そのインスタンスポインタ(thisポインタ?)」を渡すことでそれが可能になるのかが分かりません。
シーンを変更するには、SceneMgrのインスタンス内のeSceneを操作する必要があります。インスタンス内の変数ですから、そのインスタンスを介してのみアクセスが可能ですよね。つまり、実際にゲーム内で使用されているシーン管理用クラスSceneMgrのインスタンスの操作をしようと思ったら、そのインスタンスを変更したい場所に渡してやらないといけません。
thisポインタを渡せば、自身のインスタンスを渡したということになるので、渡した先のクラスからSceneMgr内のeSceneにアクセスが可能になるというわけです。

(新・ゲームプログラミングの館sp6章)thisポインタの意味について理解できないので誰かご教授ください。

#1

by 神田空田 » 5年前

C++を勉強中の者で、基礎的なことが読んでもわからないので、ご教授をお願いしたいです。

まず、このサイト(https://dixq.net/g/)の

「新・ゲームプログラミングの館/メニュー画面の作り方/sp6章メニュー画面の作り方(C++編)」(https://dixq.net/g/sp_06.html

についての質問なのですが、

インターフェースでのthisポインタの意味が分かりません。

 ここでは、ISceneChangerというインターフェースを用意して、それらをBaseSceneに実装することにより、Game・Menu・Config内で、SceneMgrに定義されたChangeSceneを使用可能にしています。

 そして、SceneMgr内で、GameかMenuかCofigを呼び出す際に引数として、thisポインタを渡しています。(SceneMgr.cppでの操作)

 このthisポインタは、最終的にmSceneChanger(BaseScene.hで定義したISceneChangerポインタ型変数)に代入されるのでしょうが、わざわざ、mSceneChangerへのthisポインタ渡しの操作をしなくてもいい気がしてしまいます。

 この記事には、

「そのインスタンスポインタをGameモジュールなどに渡して使うことでSceneMgrに実装した「ChangeSceneのみに」アクセスが可能になるわけです。」

と、書かれていますが、なぜ「そのインスタンスポインタ(thisポインタ?)」を渡すことでそれが可能になるのかが分かりません。

まだ勉強中の身ゆえ、稚拙な質問になってしまいましたが、どうか解答の方よろしくお願いします。
また、失礼な事を言ってしまっていたらご指摘お願いしますm(_ _)m


////////////////////////// SceneMgr.cpp ///////////////////////

#include "DxLib.h"
#include "Config.h"
#include "Game.h"
#include "Menu.h"
#include "SceneMgr.h"

SceneMgr::SceneMgr() :
mNextScene(eScene_None) //次のシーン管理変数
{
mScene = (BaseScene*) new Menu(this);
}

//初期化
void SceneMgr::Initialize(){
mScene->Initialize();
}

//終了処理
void SceneMgr::Finalize(){
mScene->Finalize();
}

//更新
void SceneMgr::Update(){
if(mNextScene != eScene_None){ //次のシーンがセットされていたら
mScene->Finalize();//現在のシーンの終了処理を実行
delete mScene;
switch(mNextScene){ //シーンによって処理を分岐
case eScene_Menu: //次の画面がメニューなら
mScene = (BaseScene*) new Menu(this); //メニュー画面のインスタンスを生成する
break;//以下略
case eScene_Game:
mScene = (BaseScene*) new Game(this);
break;
case eScene_Config:
mScene = (BaseScene*) new Config(this);
break;
}
mNextScene = eScene_None; //次のシーン情報をクリア
mScene->Initialize(); //シーンを初期化
}

mScene->Update(); //シーンの更新
}

//描画
void SceneMgr::Draw(){
mScene->Draw(); //シーンの描画
}

// 引数 nextScene にシーンを変更する
void SceneMgr::ChangeScene(eScene NextScene){
mNextScene = NextScene; //次のシーンをセットする
}

///////////////////////////// BaseScene.h /////////////////////////
#pragma once

#include "Task.h"
#include "ISceneChanger.h"

//シーンの基底クラス。
class BaseScene : public Task {

protected:
int mImageHandle; //画像ハンドル格納用変数
ISceneChanger* mSceneChanger; //クラス所有元にシーン切り替えを伝えるインターフェイス

public :
BaseScene(ISceneChanger* changer);
virtual ~BaseScene(){}
virtual void Initialize() override {} //初期化処理をオーバーライド。
virtual void Finalize() override ; //終了処理をオーバーライド。
virtual void Update() override {} //更新処理をオーバーライド。
virtual void Draw() override ; //描画処理をオーバーライド。

};

ページトップ