あるクラスからほかのクラスが持つリストにアクセスする

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
アバター
Hiragi(GKUTH)
記事: 167
登録日時: 13年前
住所: 大阪府
連絡を取る:

あるクラスからほかのクラスが持つリストにアクセスする

#1

投稿記事 by Hiragi(GKUTH) » 8年前

現在弾幕STGであたり判定を実装しています。
プレイヤーの弾や敵の弾などをstd::listで管理しています。
そしてPlayerクラスとEnemyクラスを持つManagerクラスというものがあり、そこでプレイヤーと敵の双方のあたり判定をしています。
そこでManagerからPlayerクラスのリストを参照しようとしています。リストの型がもともとC++や標準ライブラリ等が持っている型であったり、
型がグローバルに宣言されていたなら問題ないのですが、リストの型がPlayerクラスが持っている構造体であった場合、
どのようにManagerクラスから参照すればよいのでしょうか。
つまりPlayerクラスからShot_tの型を返す(?)にはどうすれば良いのでしょうか

前回のトピックの質問があまりにも漠然としていたので、ある程度方針を固めて(ManagerからPlayerクラスの情報を参照する)みました。

C++ / DxLib 3.16b
VS Community 2015

Managerクラス あたり判定の関数とコンストラクタ

コード:

Manager::Manager()
{
	g_cnt = 0;
	m_player = new Player;
	m_back = new Back;
		//敵は面倒なので別関数で初期化
	LoadEnemyData();
}

void Manager::CollisionAll()
{
		//敵座標
	float ex,ey;
		//プレイヤーの弾の分ループ

	//既存の型なら std::list<int> *tmp; などとしてポインタ変数を宣言、定義
	//tmp = m_player->GetShotInfo();みたいにポインタを取得
	//for(std::list<int>::iteretor blItr = *tmp.begin;blItr != *tmp.end();)でループさせて
	//blItr->xとかで参照してあたり判定を行える...がリストの型(Shot_t)がPlayerしか持ってないのでリストを宣言できない
}
Playerクラス
Player.h

コード:

#ifndef DEF_PLAYER_H

#define DEF_PLAYER_H

#include <list>

class Player
{
private:
	・・略・・

		//ショットのパラメータ
	const float SHOT_SPEED = 4.0f;		//ショット速度
	const float SHOT_COLLISION = 16.0f;	//ショットあたり判定半径
	int img_shot;						//画像ハンドル

	typedef struct Shot_t
	{
		float x;	//座標、x成分、y成分、角度、速度
		float y;
		float vx;
		float vy;
		float ang;
		float speed;
		int sizeX;	//弾のサイズ、カウンタ
		int sizeY;
		int cnt;
		int knd;	//弾の種類
	}Shot_t;
		//リストで管理してみる
	std::list<Shot_t> bullet;

private:
		//更新
	void Update();
		void Move();
		void Anim();
		void Shot();

		//描画
	void Draw();

	void Finalize();

public:
	Player();
	~Player();
		//座標を返す
	void GetPos(float *x, float *y);
		//プレイヤーの弾の情報を返す
	auto GetShotInfo();
		//プレイヤーのあたり判定のサイズを返す
	float GetSize(){return PLAYER_COLLISION;}
		//プレイヤーの弾のあたり判定のサイズを返す
	float GetShotSize(){return SHOT_COLLISION;}
		//プレイヤーが持つ弾の数を返す
	void All();


};

#endif 
Player.cpp GetShotInfo関数

コード:

auto Player::GetShotInfo()
{
		//bulletへのポインタを返す
	return &bullet;
}
だいがくせい!

sleep

Re: あるクラスからほかのクラスが持つリストにアクセスする

#2

投稿記事 by sleep » 8年前

参照したいクラスの内で Manager を friend class として指定すると、参照したいクラス内からアクセスした場合と同様に Manager からも参照したいクラス内で定義された型やメンバに直接アクセスできるようになります。

コード:

#include <iostream>
#include <string>
#include <vector>
using namespace std;

class Player
{
public:
	Player()
	{
		v.emplace_back(PlayerInfo{ "player name" });
	}
private:
	struct PlayerInfo
	{
		string name;
	};
	vector<PlayerInfo> v;
private:
	friend class Manager;
};

class Enemy
{
public:
	Enemy()
	{
		v.emplace_back(EnemyInfo{ "enemy name" });
	}
private:
	struct EnemyInfo
	{
		string name;
	};
	vector<EnemyInfo> v;
private:
	friend class Manager;
};

class Manager
{
public:
	void func()
	{
		Player::PlayerInfo a = player.v[0];
		cout << a.name << endl;
		cout << enemy.v[0].name << endl;
	}
private:
	Player player;
	Enemy enemy;
};

int main()
{
	Manager manager;
	manager.func();

	cin.ignore();
}

YuO
記事: 947
登録日時: 13年前
住所: 東京都世田谷区

Re: あるクラスからほかのクラスが持つリストにアクセスする

#3

投稿記事 by YuO » 8年前

Hiragi(GKUTH) さんが書きました:型がグローバルに宣言されていたなら問題ないのですが、リストの型がPlayerクラスが持っている構造体であった場合、
どのようにManagerクラスから参照すればよいのでしょうか。
つまりPlayerクラスからShot_tの型を返す(?)にはどうすれば良いのでしょうか
根本的に,privateな型を返すようなことをしてはいけません。
# 公開のベースクラスへのポインタや参照が戻り値の型の場合を除く。
簡単に言うと,現状は設計ミスの状態です。

privateな型はあくまで自身の実装のための型であって,public/protectedなインターフェースとして露出させてはいけません。
# 同じく,protectedな型はpublicなインターフェースとしてはいけない。

これに関しては,大前提なのでprivateな型を返すということは諦めてください。
例えば,公開のベースクラスへのポインタ (スマートポインタ) を返すような実装するとか,そもそもManagerクラスがループを回さない (Playerクラスが処理を行う) とか,
根本的な実装変更を行う必要があります。

sleep

Re: あるクラスからほかのクラスが持つリストにアクセスする

#4

投稿記事 by sleep » 8年前

一応、疑問にもお答えしておきます。
Hiragi(GKUTH) さんが書きました: つまりPlayerクラスからShot_tの型を返す(?)にはどうすれば良いのでしょうか
Player.cpp GetShotInfo関数

コード:

auto Player::GetShotInfo()
{
		//bulletへのポインタを返す
	return &bullet;
}
GetShotInfo関数の戻り値の型に auto を指定されてますよね。(Shot_tの型は privateで定義されてあるため、外部で明示的には使用できないので 必然的に受け取り側の型は auto にするしかない)
auto には templateが使用されています。
コンパイル単位上で 左辺値(戻り値の受け取り先)より前に実装を存在させれば、戻り値側 auto の型が判明し それにより受け取り側の型 auto が確定するのでパースが解決し返せるようになります。(つまり、分割コンパイルを行わない)

Player.h

コード:

#pragma once
#include <string>
#include <vector>

class Player
{
private:
	struct PlayerInfo
	{
		std::string name;
	};
	std::vector<PlayerInfo> v = { { "player name" } };
public:
	auto& get();
};

auto& Player::get()
{
	return v;
}
test.cpp

コード:

#include <iostream>
#include <string>
#include <vector>
#include "Player.h"
using namespace std;

int main()
{
	Player player;
	for (auto& info : player.get())
	{
		cout << info.name << endl;
	}

	cin.ignore();
}


逆に言えば 戻り値の型として auto を使用しなければ返せます。(分割コンパイルも可能)


Player.h

コード:

#pragma once
#include <string>
#include <vector>

class Player
{
private:
	struct PlayerInfo
	{
		std::string name;
	};
	std::vector<PlayerInfo> v = { { "player name" } };
public:
	std::vector<Player::PlayerInfo>& get();
};
Player.cpp

コード:

#include "Player.h"

std::vector<Player::PlayerInfo>& Player::get()
{
	return v;
}
test.cpp

コード:

#include <iostream>
#include <string>
#include <vector>
#include "Player.h"
using namespace std;

int main()
{
	Player player;
	for (auto& info : player.get())
	{
		cout << info.name << endl;
	}

	cin.ignore();
}

アバター
Hiragi(GKUTH)
記事: 167
登録日時: 13年前
住所: 大阪府
連絡を取る:

Re: あるクラスからほかのクラスが持つリストにアクセスする

#5

投稿記事 by Hiragi(GKUTH) » 7年前

回答してくださった方々ありがとうございます。最近プログラミングに手を付けれておらず、返信も怠っていました。
設計を根本的に変える必要があるとのことですが、それほどの時間が取れませんのですいませんが一度このトピックは閉じさせていただきます。

 また、sleepさんに提示していただいた方法で要素にアクセスできるようにはなるようですが、YuOさんの指摘により、その方法での解決は
見送ることにしました。

回答していただいたのにかかわらず、長い間返信をせず、申し訳ありませんでした。
だいがくせい!

閉鎖

“C言語何でも質問掲示板” へ戻る