質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
オブジェクト指向

オブジェクト指向プログラミング(Object-oriented programming;OOP)は「オブジェクト」を使用するプログラミングの概念です。オブジェクト指向プログラムは、カプセル化(情報隠蔽)とポリモーフィズム(多態性)で構成されています。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

DirectX

DirectX(ダイレクトエックス)は、 マイクロソフトが開発したゲーム・マルチメディア処理用のAPIの集合です。

Q&A

解決済

1回答

1351閲覧

DirectX シーンとオブジェクトの相互参照でエラーが出る

piced

総合スコア60

オブジェクト指向

オブジェクト指向プログラミング(Object-oriented programming;OOP)は「オブジェクト」を使用するプログラミングの概念です。オブジェクト指向プログラムは、カプセル化(情報隠蔽)とポリモーフィズム(多態性)で構成されています。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

DirectX

DirectX(ダイレクトエックス)は、 マイクロソフトが開発したゲーム・マルチメディア処理用のAPIの集合です。

0グッド

0クリップ

投稿2021/08/14 17:24

編集2021/08/14 18:31

#やりたいこと
あるシーンが持っているオブジェクト同士でアクセスしたい。

例えば、ゲームシーンクラスのメンバ変数にプレイヤーと敵がいた時、
プレイヤーから敵にアクセスしたい。

#問題
プレイヤーや敵などのオブジェクトを初期化するときに、
ゲームシーンへのポインタをオブジェクトに持たせることでシーンへアクセスしようとしたら、
「ゲームシーン」と「プレイヤー」で相互参照が発生しコンパイルが通らない。

#試したこと
前方宣言をしてみましたが、エラーが出てしまいます。

scene_test.h(12): error C2079:

'TestScene::player' が 未定義の class 'Player' で使用しています。

#質問
0. この問題を解決する方法を教えてください。
0. 「やりたいこと」を達成する上でこれよりもいい方法がありましたら教えてください。

※1つだけでも構いません。答えられることがありましたらどんどん教えてください。

#ヘッダー

C++

1//Scene_Test.h 2#pragma once 3 4#include "BaseScene.h" 5#include "Player.h" 6#include "Grid.h" 7#include "Wall.h" 8class Player; //前方宣言 9 10class TestScene : public IScene 11{ 12private: 13 Player player; 14 Wall wall; 15 16public: 17 void Init()override; 18 void Uninit()override; 19 void Update()override; 20 void Draw()override; 21 22 Wall GetWall(); 23}; 24 25

C++

1//Player.h 2#pragma once 3 4#include "object.h" 5#include "Vector2.h" 6#include "collision2d.h" 7#include "Scene_Test.h" 8class TestScene; //前方宣言 9 10class Player :public GameObject 11{ 12private: 13 TestScene *m_scene; 14 float m_jumpHight; 15 float m_walkSpeed; 16 float m_gravity; 17 Vector2 m_velocity; 18 Collision2D m_collision; 19 20public: 21 void Init(TestScene *ownerScene); 22 void Draw()override; 23 void Update(); 24};

#現在のシーンクラスとオブジェクトクラスの関係図
イメージ説明

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

TestSceneのメンバ変数のplayerはポインタの間違いではないでしょうか?

c++

1class Player; //前方宣言 2class TestScene : public IScene 3{ 4private: 5 Player* player; //←

前方宣言を使う場合、その型の内容詳細は不要なので、当該ヘッダのインクルードはソースで行うようにすると良いかと思います(この場合、Player.hのインクルードはScene_Test.hではなく、Scene_Test.cppで行う)。

なお、参照できないのはインクルードガードが働いて、Player.hの内容が展開されていないためです。

投稿2021/08/14 21:21

Serbonis

総合スコア586

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Serbonis

2021/08/14 21:27

Playerをポインタではなく実体として宣言したい場合は、Player.hからScene_Test.hのインクルードを外して、Player.cppでインクルードするようにします。この場合、Scene_Test.hでのclass Player;の前方宣言は冗長で不要です。
Serbonis

2021/08/14 23:37

TestSceneでPlayerを実体で持ってしまうと、Playerを変更するたびにTestScene* m_sceneを持つすべてのクラスでリビルドが必要になります。ポインタであればPlayerを実際に参照しているファイルのリビルドだけで済みます。これはWallクラスやこの先追加されるであろうEnemyクラスでも同様で、これらのクラスを一つでも修正すると全リビルドになってしまい、制作時間の長大化に繋がります。
Serbonis

2021/08/14 23:58 編集

ポインタで持つ場合は下記のような初期化方法もあります。ご参考までに。 ```C++ // Scene_Test.h class Player; class TestScene : public IScene { public: TestScene() : player( new Player(this) ){} ~TestScene(){ delete player; } private: Player* const player; }; // Player.h class TestScene; class Player :public GameObject { public: Player() = delete; Player( TestScene* p ) : m_scene(p){} private: TestScene* const m_scene; }; ```
piced

2021/08/15 09:44

見事にポインタ、非ポインタで理想的な実装ができました! 再び会世話になりました。 ちょっとした質問が2つあるのですが、 1つ、ゲーム開発ではnew deleteをなるべく使うべきと以前学んだのですが、 どこまでをポインタ変数を使って、どこからは実体の変数を使うべきなのでしょうか? 2つ、提示していただいたコードの player( new Player(this) ){} ←この書き方を知らないのですが これって何をしているのでしょう?書き方の名前とかありますでしょうか?
Serbonis

2021/08/15 16:26

1.ゲームでは登場するオブジェクトの個数を予め決めておく事が難しいので、出現する都度に生成(new)して、不要になったら削除(delete)します。つまりゲームオブジェクトはほとんどすべてです。 2.コンストラクタの初期化子でメンバ変数を初期化しています。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問