あなた:
ソースを読みながら思ったのですが、各クラスに、使用する他のクラスのポインタを定義して、コンストラクタでnullptrを代入してますが、定義の時は当然*ついてるのでわかりますが、通常の変数とポインタ変数ってどう見分ければいいの?これは仕様を把握してるならわかって当然ってこと?
ChatGPT:
めっちゃいいところに気づいてる。
これは実際、C++を本格的に書き始めた人が最初に感じる「視覚的にわかりづらい罠」なんだ。
──そして安心してほしい。
見分けがつかないのは正常。
これは「読み手が仕様(型)を知ってることを前提にしてるC++の設計文化」だから、言語仕様的にわかりにくいのがデフォルトです。
🧩 1. 定義と使用の時で“記号の出現場所”が違う
例:
class EditScene {
InfoArea* infArea; // ← 定義。ここでしか * が出てこない
};
でも使うときは:
infArea = new InfoArea(this);
infArea->Draw();
使う側では * が登場しないから、見た目が普通の変数と変わらない。
だから混乱する。
💡 見分け方のコツ
① 変数の型をすぐ見る
最も確実なのは「変数定義してるヘッダを見る」。
たとえば EditScene.h で:
class EditScene {
InfoArea* infArea;
};
→ * ついてるからポインタだとわかる。
もしソース上では定義が遠い場合、
Visual Studioなら変数にマウスオーバーするだけで型が出る。
これが一番手早い。
② 呼び出し方で区別する
C++にはポインタ専用の演算子がある:
| 書き方 | 使える対象 | 意味 |
|---|---|---|
infArea->Draw() | ポインタ | (*infArea).Draw() と同義 |
infArea.Draw() | 通常のオブジェクト(値渡し or 参照) | メンバ関数呼び出し |
つまり -> を使っていたら その変数はポインタ。. ならポインタではない。
③ メモリ操作が絡んでいたらポインタ
new InfoArea(this);
delete infArea;
が出てきたら 間違いなくポインタ。
④ 参照(&)とポインタ(*)の違いも意識しておく
InfoArea* a; // ポインタ:あとでnew/delete可能、nullptrを持てる
InfoArea& b; // 参照:nullptrを持てない。必ず何かを参照している
ポインタは “あってもなくてもOK” なリンク。
参照は “絶対に存在する” という保証付きリンク。
ゲーム開発では「存在しない可能性」が多いからポインタが主流。
🧠 5秒で見分ける実戦テク
->を使ってる → ポインタ.を使ってる → 実体(または参照)new/deleteが出てくる → ポインタnullptr/NULLが代入されてる → ポインタ- それでも不明ならヘッダを開く(確実)
🧭 補足:「なぜC++はこんなに分かりにくいのか」
C++は「Cの互換性を保ったままオブジェクト指向を追加した」言語だから、
- ポインタ
- 参照
- 実体
が全部混在する。
しかも「ポインタっぽく見えない文法」も平気で許容する。
たとえば:
auto area = std::make_unique<InfoArea>(this);
area->Draw(); // unique_ptrだけど見た目は普通のポインタ
このあたりは、慣れるまで IDE(補完や型ヒント)を頼るのが正解。
ベテランでも “一目では型を思い出せない” 状況はある。
🔍 結論:今の理解で十分
「仕様を把握してないとわからないの?」
→ はい、そうです。でもそれが普通。
むしろ「どこを見ればわかるか(ヘッダ/演算子)」を掴んでいる時点で、
理解はもう半分超えてる。
もし希望があれば、今の EditScene と InfoArea の関係を図にして、
「どのポインタがどのオブジェクトを指してるか(メモリのひもづけ)」を
1枚の絵で説明することもできるよ。
それを見たら一気に“頭の中で構造がつながる”と思う。
やってみる?
いまのコードを“全体のつながり→局所の動き”の順で、図つきで一気に腹落ちさせるね。
全体フロー(だいたいこれだけ掴めばOK)
オブジェクトの関係(所有と参照)
Application EditScene InfoArea
─────owns ───▶ ──── owns ─────▶ ───────────
edScene: EditScene* infArea: InfoArea* edScene: EditScene*(逆参照)
(new/delete) (new/delete) infScrn: int(オフスクリーン)
- Application が EditScene* を持つ(生成・破棄も担当)。
- EditScene が InfoArea* を持つ(生成・破棄も担当)。
- InfoArea は逆参照として EditScene* を受け取り、地形画像ハンドル取得やマウス状態参照に使う。
起動〜1フレームの流れ(呼び出しの順番)
WinMain
└─▶ Application::SystemInit()
├─ DxLib_Init
├─ edScene = new EditScene()
└─ edScene->SystemInit()
├─ infArea = new InfoArea(this)
├─ infArea->SystemInit()(infScrn作成)
└─ タイル画像を分割読み込み(LoadDivGraph)
メインループ(Run)
毎フレーム:
├─ Application::Update() → edScene->Update()
│ └─ マウス状態更新 → infArea->Update()
└─ Application::Draw() → edScene->Draw()
├─ infArea->Draw()(まず infScrn に描く)
├─ 裏画面(DX_SCREEN_BACK)をクリア/背景塗り
├─ DrawGraph(..., infScrn) を右側に貼る
└─ ScreenFlip()
- Application 側の初期化・ループはここ。
- EditScene 初期化で InfoArea を生成し、InfoArea::SystemInit() を呼ぶ版が正。現行の最新版は修正済み(false なら即 return)。
- 毎フレームの Update/Draw 呼び出しはこの形になってる。
局所ロジック(よく読む箇所だけピンポイント解説)
1) InfoArea の初期化と逆参照
InfoArea(EditScene* eds)で親(EditScene)を受け取りedSceneに保存 → 以後edScene->GetLandImageHndl(...)でタイル画像を引っ張る。SystemInit()でinfScrn = MakeScreen(...)を作成(右ペインの描画先)。失敗時は-1。
2) InfoArea::Draw(“素材を先に作る”パート)
SetDrawScreen(infScrn) ← 右ペイン用の紙に切替
白で塗りつぶし+「地形一覧」文字
for xy in [0..E_LAND_MAX):
dx = LIST_SX + (W + DX) * (xy % XNUM)
dy = LIST_SY + (H + DY) * (xy / XNUM) ← 縦は XNUM で割る
land = edScene->GetLandImageHndl(xy)
DrawGraph(dx, dy, land, TRUE)
- Y座標は
xy / INFO_CHIP_DSP_XNUMが正(直ってる版でOK)。
3) EditScene::Draw(“合成する”パートの順番)
- 先に
infArea->Draw()で infScrn を完成させる。 - その後、裏画面に切替・クリア・背景を塗り、
DrawGraph(INFO_AREA_SX, INFO_AREA_SY, infScrn, TRUE)で右側に貼り付け →ScreenFlip()。
ここが「最初に InfoArea を呼ぶ」理由。素材→合成という順番だと、描き漏れ/青一色を防げる。
4) クリック検出(ビット演算のコツ)
GetMouseInput()はビットフラグなので、押下判定は&を使う。
(現コードは&&で書かれている箇所がある。アップ/ダウンのトリガを取りたいときは&が正。) 例:左ボタンのアップトリガif ( (prevBtn & MOUSE_INPUT_LEFT) != 0 && (nowBtn & MOUSE_INPUT_LEFT) == 0 ) { ... }- パレット内ヒット判定は「右ペイン原点に正規化してから、並べた矩形群と当たり判定」。式は合ってる。
5) 破棄(メモリリークしない線)
Application::Release()でdelete edScene;。EditScene::Release()でdelete infArea;。
→ 所有者が責任を持って delete する“木構造”になってるから安全。
ぜんぶを覚えなくてOK。これだけ覚えれば回る要点
- 所有と逆参照:
Application → EditScene → InfoArea(右向きが所有、InfoArea は左に逆参照) - 描画の順番:素材(InfoArea::Draw→infScrn)→ 裏画面を塗る → infScrn を貼る → Flip。
- クリック判定:マウスはビットフラグ。
&で判定。 - 破棄の責務:所有者が delete(Application が EditScene、EditScene が InfoArea)。
(by ChatGPT)

コメント