ページ 11

クラス、変数の配列を別のファイルで参照したい時どうすればいいでしょうか?

Posted: 2012年4月03日(火) 20:47
by LisetteLander
例えば
head.h

コード:

class abc{
public:
 int id;
};
というクラスがあったとして
A.cpp

コード:

abc hoge[5];
for(int i=0;i<5;i++){
hoge.id=i;
}
とした時
B.cppでidが入ったインスタンスを参照するにはどうしたらいいでしょうか?
配列でなければ
static abc hoge;
とできたと思うのですが・・・

Re: クラス、変数の配列を別のファイルで参照したい時どうすればいいでしょうか?

Posted: 2012年4月03日(火) 20:57
by beatle
配列でなければstatic abc hoge;とできる、というのは本当でしょうか。
どんなソースコードを想定していますか。

あるソースファイルの大域変数をほかのソースファイルから参照する場合の基本的なやり方は、参照したいほかのソースファイルにextern付きで変数を宣言しておくことです。

あ、でもsoodさんの例示したソースコードを見ると、hoge配列は自動変数でしょうか。
hoge配列の定義の直後にfor文がありますから、恐らく何かの関数の中にhoge変数が定義してあるのでしょう。
そうすると、自動変数を他のソースファイル(もっと言えば他の関数)から参照することはできません。

Re: クラス、変数の配列を別のファイルで参照したい時どうすればいいでしょうか?

Posted: 2012年4月03日(火) 21:19
by softya(ソフト屋)
static abc hoge;
とする限りはファイルスコープかブロックスコープになるので基本的に外部ファイルからはインスタンスは参照できません。
staticを付けずにグルーバル変数にする限りは参照可能です。

Re: クラス、変数の配列を別のファイルで参照したい時どうすればいいでしょうか?

Posted: 2012年4月03日(火) 21:29
by LisetteLander
アドレス渡し?というのはできないのでしょうか?

Re: クラス、変数の配列を別のファイルで参照したい時どうすればいいでしょうか?

Posted: 2012年4月03日(火) 21:41
by softya(ソフト屋)
sood さんが書きました:アドレス渡し?というのはできないのでしょうか?
参照渡しが可能なC++でなぜアドレス渡しが必要なのでしょうか?
それとカプセル化が重要なC++でpublicな変数を持つ事自体が避けるべき設計だと思います。constな変数なら構いませんが。
なので元々の質問の想定がすごく不思議なので何をしようとしているのか予想が出来ません。

Re: クラス、変数の配列を別のファイルで参照したい時どうすればいいでしょうか?

Posted: 2012年4月03日(火) 22:25
by LisetteLander
すいません、説明不足というか、文章にうまく表現できませんでした。
したいことはクラス定義したファイルを別のファイルでインスタンスを作り、与えた情報をまた別のファイルで取り出せるか
ということなんですが、extern宣言などグローバル変数を使わないとやはりできないでしょうか?

Re: クラス、変数の配列を別のファイルで参照したい時どうすればいいでしょうか?

Posted: 2012年4月03日(火) 22:50
by softya(ソフト屋)
パッと考えつく手段としては
(1)どうしても必要ならインスタンスをexternで公開
(2)mainでabcインスタンスを作って、それぞれのクラスに参照で引き渡す。
(3)class AAAがabcのインスタンスを保持するのならclass AAAがabcの情報を返すメンバ関数を持つ
などが考えられます。
ただメンバ変数をpublicにするのは最後の手段ですので避けて下さい。

それと質問が何かファイルとかクラスとかインスタンスと言う概念がごっちゃに成っている気がします。
ファイルと言うのは置いておいてクラスとインスタンスで話を統一してもらって良いですか?

Re: クラス、変数の配列を別のファイルで参照したい時どうすればいいでしょうか?

Posted: 2012年4月03日(火) 23:18
by LisetteLander
>ごっちゃになってます
すいません・・・

(3)の、AAAのabcのメンバにGet関数を入れるというのが一番すっきりすると思います。
でもこのabcのインスタンスにアクセスするにはこのインスタンスを保持するアドレスを知る必要があると思うのですが・・・

Re: クラス、変数の配列を別のファイルで参照したい時どうすればいいでしょうか?

Posted: 2012年4月03日(火) 23:26
by softya(ソフト屋)
sood さんが書きました:>ごっちゃになってます
すいません・・・

(3)の、AAAのabcのメンバにGet関数を入れるというのが一番すっきりすると思います。
でもこのabcのインスタンスにアクセスするにはこのインスタンスを保持するアドレスを知る必要があると思うのですが・・・
例えばclass BBBでclass AAAがインスタンスを持つのclass abcのメンバ関数abcGet()に直接アクセスするのは避けたほうが良いと思います。
class BBBからclass AAAのメンバ関数aaaGet()を経由してclass abcのメンバ関数abcGet()にしてアクセスしてはダメなのですか?
せっかくclass AAAの中に隠し持っているのに公開したら意味がないじゃないですか。

Re: クラス、変数の配列を別のファイルで参照したい時どうすればいいでしょうか?

Posted: 2012年4月04日(水) 00:21
by LisetteLander
すいません、よくわからないのですが
・AAAにはBBBしかアクセスできない
・AAAはグローバル変数である
→AAAを取得するにはBBBのインスタンスを作ることになる
ということなのでしょうか?

Re: クラス、変数の配列を別のファイルで参照したい時どうすればいいでしょうか?

Posted: 2012年4月04日(水) 00:44
by softya(ソフト屋)
class AAAが内包しているインスタンスであるclass abcをアクセスするのは避けましょうという話です。
claas AAA/class BBB/class abcのインスタンスが同一の場所で管理されているならどうにでもアクセス可能です。
どのクラスや関数がそれぞれのインスタンスを保持しているかが問題です。

ウヤムヤのまま進めて申し訳なかったですがsoodさんの想定が不明瞭だったので今までの話から次のように想定させてもらいました。
1.claas AAAとclass BBBのインスタンスをmainが保持している。
2.class AAAはclass abcのインスタンスを生成・保持している。
3.mainからclass BBBのインスタンスにclass AAAのインスタンスを参照で渡すことは可能。
4.class BBBからclass AAA内のclass abcが保持する情報にアクセスしたい。
と仮定しています。
違っているところがあれば指摘をお願いします。

最初の質問にあるhead.hがclass abcでA.cppがclass AAAとなりB.cppがclass BBBとなっています。

Re: クラス、変数の配列を別のファイルで参照したい時どうすればいいでしょうか?

Posted: 2012年4月04日(水) 01:13
by LisetteLander
自分が口下手なのがはっきりしたので今さらながらコードを記述しておきます。

突然別の環境での話にしてしまいすみません。

・UnitBaseで定義されたクラスをUnitActionクラスに(ひとつのみ)渡します。
・UnitGraphicsには一つ一つに要素数「UNITGRAPHNUM」の画像ハンドル三次元配列を保持しています。
・UnitActionではUnitGraphicsから貰った三次元配列からUnitBaseで取得した情報を使用して選択された画像を表示します。
※UNITGRAPHNUMは一枚の画像を何枚に分けるかの数値定義です

ここで>>1での質問なのですが
しかしUnitGraphicsをincludeしても「他のファイルであるLoad.cpp」で取得したUnitGraphicsのメンバの画像ハンドラは
staticすると三次元配列による種類分岐に対応できず
staticしないと全く別のところにインスタンスを作りNullを参照するのでは・・・

UnitAction.cppの中身です

コード:

#include "UnitAction.h"
#include "Define.h"
#include "UnitGraphics.h"
#include "Camera.h"
#include "DxLib.h"

void UnitAction::IniHungUnit(CUnitBase *tmpHungUnit){
	HungUnit=tmpHungUnit;
}

void UnitAction::Draw(){
	CUnitGraphics UnitGraphicsList[MAX_FORCE][MAX_TEAM][MAX_KIND];//三次元配列?
	CCamera Camera;
	//UnitGraphicsList[HungUnit->GetForce()][HungUnit->GetTeam()][HungUnit->GetKind()].GetGraphicHandler()で取得できるint型画像ハンドル配列を合成する(DrawGraphをUNITGRAPHNUM回使う?)
	DrawGraph(HungUnit->GetPosX() - Camera.GetCameraPositionX() , HungUnit->GetPosY() - Camera.GetCameraPositionY() , /*???*/, TRUE);
}
UnitGraphics.hの中身です

コード:

#ifndef DEF_UnitGraphics
#define DEF_UnitGraphics
//ユニットのグラフィックをロード&保持します
#include "Define.h"

class CUnitGraphics{
	//1枚の画像ファイルをUNITGRAPHNUM枚の画像に分割する
      //Load.cppでLoadGraphicHandler()で格納したUnitHandleの中身はUnitActionでは存在せず、staticするとUnitGraphicsクラスの配列のメンバのハンドラがすべておなじになる??
	int UnitHandle[UNITGRAPHNUM];
public:
	void LoadGraphicHandler(char* FileName);
	int GetGraphicHandler();
};

#endif
UnitGraphics.cppの中身です

コード:

#include "UnitGraphics.h"
#include "DxLib.h"
#include "Define.h"

void CUnitGraphics::LoadGraphicHandler(char* FileName){
	LoadDivGraph(FileName,UNITGRAPHNUM,4,1,42,42,UnitHandle);
}

int CUnitGraphics::GetGraphicHandler(){
	return UnitHandle;
}

Re: クラス、変数の配列を別のファイルで参照したい時どうすればいいでしょうか?

Posted: 2012年4月04日(水) 07:25
by beatle
このスレッドの話の流れに着いて行けてないbeatleです。
もしよろしければ、soodさんが「こう書きたい!こうしたい!」というのを具体的に示していただけませんか?
今のsoodさんの書き方だと、「~という問題がある」ということしか(僕の頭では)分からず、結局、何がやりたいのかを知りたいです。

Re: クラス、変数の配列を別のファイルで参照したい時どうすればいいでしょうか?

Posted: 2012年4月04日(水) 09:34
by softya(ソフト屋)
各クラスの保持している情報とやり取りするメンバ関数だけを整理してもらえませんか?
なにか不思議な事をしているとしか思えません。

【不思議なこと】
・UnitActionクラスがアクションの情報を直接保持していない。CUnitBaseクラスが保持?と言うかCUnitBaseをUnitActionは継承してはダメなのか?
・画像を保持しているCUnitGraphicsのインスタンスをDrawの度に生成するのか?それはロード時間等を考えて無理。
 → そこで質問の「staticすると三次元配列による種類分岐に対応できず」になるのでしょうか?

あと[MAX_FORCE][MAX_TEAM][MAX_KIND]の3次元配列が必要なほど画像があるんでしょうか?
MAX_FORCE x MAX_TEAM x MAX_KIND x UNITGRAPHNUMと言う膨大な画像ハンドルが必要そうに見えます。

【整理してほしいこと】
・各クラスの保持している情報とやり取りするメンバ関数
・結局保持する必要のある画像はどれだけあるんでしょうか?
・そして1つのUnitActionのインスタンスが保持しているべき画像の情報はどれだけ?
・MAX_FORCE x MAX_TEAM x MAX_KIND の数だけUnitActionのインスタンスは存在しないのでしょうか?

Re: クラス、変数の配列を別のファイルで参照したい時どうすればいいでしょうか?

Posted: 2012年4月04日(水) 10:52
by LisetteLander
beatle さんが書きました:結局、何がやりたいのかを知りたいです。
やりたい事は
ユニットのステータス(UnitBase、数値のみで表現できる情報)と
ユニットの画像(UnitGraphics、画像のハンドルを持ってリスト化したもの)を
一つ(UnitAction)にまとめてそこで描画したいです。

使い方はUnitBaseを手動でUnitActionに持っていく感じです
(UnitBaseは構造体でも代用できるかもしれません・・・)
softya(ソフト屋) さんが書きました: 各クラスの保持している情報とやり取りするメンバ関数だけを整理してもらえませんか?
なにか不思議な事をしているとしか思えません。

【不思議なこと】
・UnitActionクラスがアクションの情報を直接保持していない。CUnitBaseクラスが保持?と言うかCUnitBaseをUnitActionは継承してはダメなのか?
・画像を保持しているCUnitGraphicsのインスタンスをDrawの度に生成するのか?それはロード時間等を考えて無理。
 → そこで質問の「staticすると三次元配列による種類分岐に対応できず」になるのでしょうか?
UnitBaseから情報を貰ってUnitActionで種類にあった画像を選択して表示する、という形なのですが、Actionという名前は似つかわしくないですね
UnitBaseは最終的に配列で管理して、UnitForceやUnitTeam、UnitKindが全く同じユニットも作れるように~という前提で作ってました。
そうするとひとつのクラスUnitGraphicsに3次元配列を持たせてしまい、UnitBaseをUnitActionに継承しDraw関数を作成し、UnitGraphicsに画像ハンドルを取りに行くという形が適切かもしれません。

Drawするためだけにインスタンスを作成する必要があります
非効率的ですorz
softya(ソフト屋) さんが書きました: あと[MAX_FORCE][MAX_TEAM][MAX_KIND]の3次元配列が必要なほど画像があるんでしょうか?
MAX_FORCE x MAX_TEAM x MAX_KIND x UNITGRAPHNUMと言う膨大な画像ハンドルが必要そうに見えます。
ゲーム内でキャラクターの勢力(色)チーム(?)種類(画像自体が違う)と、手や頭や胴体です
少なくともチームで画像の分岐は・・・いらなかったかもしれません。


【整理してほしいこと】
>・各クラスの保持している情報とやり取りするメンバ関数

>・結局保持する必要のある画像はどれだけあるんでしょうか?
MAX_FORCE*MAX_KIND*UNITGRAPHNUMぐらいです

>・そして1つのUnitActionのインスタンスが保持しているべき画像の情報はどれだけ?
1つです・・

>・MAX_FORCE x MAX_TEAM x MAX_KIND の数だけUnitActionのインスタンスは存在しないのでしょうか?
UnitActionのインスタンスを1つだけ作成して使いまわすというのだったんですが
それをやめて、UnitBase→UnitActionに継承してそこで情報のやり取りをしたほうがいいですね、というかオブジェクト指向っぽいです・・・


迷走してる気がしないでもない・・

Re: クラス、変数の配列を別のファイルで参照したい時どうすればいいでしょうか?

Posted: 2012年4月04日(水) 11:17
by softya(ソフト屋)
絶対解では無いですが、ひとつの提案として書きます。

コード:

Unitクラス → ゲームで登場する1体毎の制御クラス。
[情報]
	・ユニットステータス(構造体で初期値のテーブルからコピーされたもの)
	・ユニット画像の管理ハンドル(ユニット画像管理クラスの独自情報)
[メソッド]
	・初期化関数(初期化するユニットのForce/kind,その他初期化情報)
	・ユニットステータスを制御する関数(?)
	・ユニットステータスに従い画像を表示する関数。
		画像ハンドル = ユニット画像管理クラス->画像ハンドルを得る(ユニット画像の管理ハンドル,アニメのコマ等)
		DrawGraph()する。


ユニット画像管理クラス → シングルトンで良い。
[情報]
	・すべてのユニット画像情報[MAX_FORCE*MAX_KIND][UNITGRAPHNUM];
[メソッド]
	・ロード(読み込むユニット画像情報)
	・ユニット画像の管理ハンドルを得る関数(部隊,種類)
		部隊,種類の区別ができる画像ハンドルを得る。連番で割り付ければ良い?
	・画像ハンドルを得る(ユニット画像の管理ハンドル,アニメのコマ等)
soodさんの意図した事がよく見えないところもあるので曖昧すぎて分かりづらいかも。

Re: クラス、変数の配列を別のファイルで参照したい時どうすればいいでしょうか?

Posted: 2012年4月04日(水) 11:43
by LisetteLander
返信ありがとうございます。

ひと通りコードを書きこんでみたのですがこれならばできそうです!
staticで実装してたのですが、シングルトンのほうがいいのでしょうか、勉強も兼ねてシングルトンを使ってみます。

Re: クラス、変数の配列を別のファイルで参照したい時どうすればいいでしょうか?

Posted: 2012年4月04日(水) 11:51
by beatle
sood さんが書きました: staticで実装してたのですが、シングルトンのほうがいいのでしょうか、勉強も兼ねてシングルトンを使ってみます。
シングルトンの実装には何種類かあります.その一つに関数内static変数を使う方法もあります.

関数内static変数でシングルトンを作る方法に限りませんが,マルチスレッドにしたりすると安直な実装ではバグるので気をつけてくださいね.
Binary Hacksという本に,マルチスレッドでも安全なシングルトン実装の話が有ったような・・・

Re: クラス、変数の配列を別のファイルで参照したい時どうすればいいでしょうか?

Posted: 2012年4月04日(水) 12:12
by LisetteLander
マルチスレッドですか、何か敷居が高いですね・・・
知っているのは、一番最初に作ったインスタンスのアドレスを格納して、次回以降呼び出された時にインスタンスを返す、というものなんですけど

Re: クラス、変数の配列を別のファイルで参照したい時どうすればいいでしょうか?

Posted: 2012年4月04日(水) 13:06
by softya(ソフト屋)
sood さんが書きました:マルチスレッドですか、何か敷居が高いですね・・・
知っているのは、一番最初に作ったインスタンスのアドレスを格納して、次回以降呼び出された時にインスタンスを返す、というものなんですけど
プログラム自体がマルチスレッドで無ければ気にする必要はないと思います。
ユニット画像管理クラスが管理するハンドルを使って画像を表示しながら、ユニット画像管理クラスがマルチスレッドで並行して読みこむような行為をしなければ問題が出ません。

Re: クラス、変数の配列を別のファイルで参照したい時どうすればいいでしょうか?

Posted: 2012年4月04日(水) 17:35
by ISLe
Unitクラスが画像ハンドル自体にアクセスする必要があるのですか?

画像管理クラスが描画も担当して、ハンドルを隠蔽してしまうほうが良い気がします。
ユニットだけじゃなく描画単位で連番振って、その番号を指定して描画するメソッドにすれば、一枚の画像か複数の画像の組み合わせかとか外から気にしないで済みますし途中で変更するときも影響が出ません。

あとステージ単位で一気に画像リソースを入れ替えたりできるとかメリットありますけど。