静的メンバ変数から始まった細かい疑問

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
moba
記事: 82
登録日時: 9年前

静的メンバ変数から始まった細かい疑問

#1

投稿記事 by moba » 9年前

追記:紛らわしい質問をしてしまってすみません。
これが元のコードで、No.2以降、問題はstaticとシングルトンの話になりました。

VC++(2010Express)/Dxlibで取り組んでいます。初心者です。
質問ばかりですみません。今回は一応動いていますが、その分応えるのに手間がかかると思います。
強調した部分が疑問点なのですが、よかったら調べ方だけでも教えていただけませんか。
下のコードですが、太文字を使うために、codeコマンドは外しました。
------------------------------------------------------
メイン関数側概略(){
    MAP *map[3];
    MAP::SetTileGraph("(画像のパス)");//静的メンバ関数に静的メンバ変数を設定させる
    for(int i=0; i<3; i++){
        map[i] = new MAP(i);
    }
}

//map.h概略
class MAP{
private:
//静的メンバ変数を宣言
    static int (色々);
    static int *tileDiv;//LoadDivGraphで返されるハンドルを入れる
    static char *tileGraph;//画像のパスを入れる
//↑定義は別にcppファイル内で行う(なぜ?ここで初期化するとerror C2864:static const int データ メンバー以外をクラス内で初期化することはできません)
public:
    static void SetTileGraph(char* file);//ここにこの関数の定義を書き込むと多重定義になった?
    static void FreeTileGraph();
};

//map.cpp概略
//静的メンバ変数の定義 なぜここで型の名前にstaticはいらない?/特に疑問:SetTileGraphで値を設定するのに定義するのが面倒!
int MAP::(色々);
int *MAP::tileDiv;
char *MAP::tileGraph;
void MAP::SetTileGraph(char* file)//なぜここで型の名前にstaticは必要無い?
{
    //ここで静的メンバ変数の値の変更(定義ではない?)
    (数値色々) = (計算結果) //この3行はいつかファイルの読み込みに置き換える
    tileHeight = 32*5;
    tileGraph = file;
    tileDiv = new int[(tileWidth/cellWidth)*(tileHeight/cellHeight)];
    if(LoadDivGraph(tileGraph,40,8,5,32,32, tileDiv) == -1)
        {
            MessageBox(NULL,tileGraph,"マップ画像の読み込み失敗",MB_OK);
            DebugBreak();
        }
}
void MAP::FreeTileGraph(){
    tileGraph = NULL;
    delete []tileDiv;
}
};
最後に編集したユーザー moba on 2015年12月22日(火) 22:58 [ 編集 1 回目 ]

アバター
Dixq (管理人)
管理人
記事: 1662
登録日時: 14年前
住所: 北海道札幌市
連絡を取る:

Re: 静的メンバ変数から始まった細かい疑問

#2

投稿記事 by Dixq (管理人) » 9年前

staticを安易に使うのはやめましょう。
const staticならいいですが、
安易にインスタンス化しなくてすむからstaticにしようという考えは悪な設計を生み出します。
(web上で「クラスの中身なんか全部staticにすればいいじゃないか」というブログを書いて笑われ者になっている人がいます)
まずはconst static以外のstaticを全部取っ払ってから再度設計してみてください。
学ぶうちにstaticを必ず使わないといけないところは出てきますが、(シングルトン等)
理解したうえで必要な個所にのみ使用してください。
少なくとも普通の変数のstatic化は危険です。

moba
記事: 82
登録日時: 9年前

Re: 静的メンバ変数から始まった細かい疑問

#3

投稿記事 by moba » 9年前

管理人さんアドバイスをありがとうございます。
自分自身何を聞きたいのか分からなかったのですが、このまま進んで良いのか不安だったようです。
ややこしい質問ですみません。

MAPクラスのオブジェクトmap[0],map[1],map[2]はそれぞれ構造体Cellの配列を持ち、
マップレイヤの1,2,3に対応します。これでRPGのマップを表現したいです。

map[0],map[1],map[2]で、

・タイル画像のパス(tileGraph)
・分割して読み込んだタイル画像のハンドル(tileDiv)
・画像に合った1マス当たりのサイズ等(色々)

の実体を共有したい(staticにしたい)と考えました。
また、いずれもマップファイル毎に代わるので、MAPクラスメンバ変数としてはconst staticにできないと考えました。

(tileGraph)は必要なく、(色々)はコンストラクタから毎回staticではないメンバ変数に読み込めばいいと思います。
(map[0],[1],[2]と実体化する時には二度手間、三度手間になってしまいますが。)

しかし、同じ画像を二度メモリに展開しないために、ハンドル(tileDiv)だけはどうしても全インスタンスで共有しなければならないと思います。
この場合は、グローバル領域にstatic int tileDivと宣言する形をとれば良いでしょうか。

メンバ変数のstaticを外す設計として、上記のように考えました。
この形なら安全なのでしょうか。

アバター
Dixq (管理人)
管理人
記事: 1662
登録日時: 14年前
住所: 北海道札幌市
連絡を取る:

Re: 静的メンバ変数から始まった細かい疑問

#4

投稿記事 by Dixq (管理人) » 9年前

携帯なのであまり詳しく書けませんが
そう言うときはシングルトンパターンという
デザインパターンを使います。
唯一無二であることが保証でき、インスタンスがどこからでも参照できます。
ゲームプログラミングの館でも紹介しているので見てください。
ただシングルトンもグローバル変数変わり身に使い始めると設計が破綻しますので十分注意して使ってください。
出来るだけインスタンスを持たせるか、インターフェイスを使って値を取得するような工夫をしてください。

moba
記事: 82
登録日時: 9年前

Re: 静的メンバ変数から始まった細かい疑問

#5

投稿記事 by moba » 9年前

DxLibの館のサンプルプログラムを見させていただきました。
分からなかったことがあるので、時間がある時にお答えいただけますか。(全く急いでいません)

シングルトンについて
・シングルトンは、機能としては単一のグローバル変数そのものに思えます。
 グローバル変数の実体を1つだけ定義するのとは違いが出るのでしょうか。

今回のケースについて
・どこにシングルトンを使うべきなのか分かりませんでした。
 tileDivはクラスの名前ではなくてクラスMAPのメンバ変数ですが、
 シングルトンパターンを使うというのはtileDivについてなのでしょうか。

アバター
Dixq (管理人)
管理人
記事: 1662
登録日時: 14年前
住所: 北海道札幌市
連絡を取る:

Re: 静的メンバ変数から始まった細かい疑問

#6

投稿記事 by Dixq (管理人) » 9年前

> シングルトンについて
>・シングルトンは、機能としては単一のグローバル変数そのものに思えます。
> グローバル変数の実体を1つだけ定義するのとは違いが出るのでしょうか。

シングルトンはそもそもインスタンスが唯一であることを保証する作り方であって、
どこからでも参照できるのはその副次的効果によるものです。
よって考え方はイコールではないですが、現実的には同じような使い方ができます。

> ・どこにシングルトンを使うべきなのか分かりませんでした。

どこにシングルトンを使うべきなのかはなかなか難しいところです。
例えばキーボードは一つだからシングルトンでいいだろうと思って作っていたら、
後々パッドに対応して、2P対戦をしたくなったとき多重化できないので、設計が破綻します。
どこが適切なのかはたくさんのコードを書いて、人のコードを読んで慣れていくしかないでしょう。

> tileDivはクラスの名前ではなくてクラスMAPのメンバ変数ですが、
> シングルトンパターンを使うというのはtileDivについてなのでしょうか。

シングルトンパターンについてちゃんと理解されていないようです。
よくキーボードクラスをシングルトンにしたサンプルをみてください。
メンバ変数について適用するものでしょうか?

見るだけでなく実際に書いてください。
自分のプログラムに適用してください。
その次はカスタマイズしてみてください。
そうしているうちに分かってくると思います。

moba
記事: 82
登録日時: 9年前

Re: 静的メンバ変数から始まった細かい疑問

#7

投稿記事 by moba » 9年前

23:07斜線部を修正

> シングルトン
はい、では自分で考え続けます。貴重な例をありがとうございます。
---
> シングルトンパターンについてちゃんと理解されていないようです。
> よくキーボードクラスをシングルトンにしたサンプルをみてください。
> メンバ変数について適用するものでしょうか?

弁明すると少し長くなるのですが…
僕はこのような流れだと思っていたので

(No.3)
僕:同じ画像を二度メモリに展開しないために、
僕:ハンドル(tileDiv)だけはどうしても全インスタンスで共有しなければならないと思います。
(No.4)
> そう言うときはシングルトンパターンという
> デザインパターンを使います。

シングルトンパターンが、3回LoadDivGraphするのを避けるのに有効なのかと思ってしまいました。
つまり、具体例では出てきませんが、実は
「1つだけ確保する」ことが、他のもの有効なのかと憶測しました。
ですが、憶測の部分ではなくて、どう繋がらないか分からないことの方を伝えるべきでした。すみません。

MAPクラスをシングルトンパターンにしても、
レイヤを3つにするためにMAP map[3]として3つインスタンスを作るため、
メンバ変数int tileDivとすると、tileDivは3つできてしまいます。
シングルトンパターンにしても一発では同じ画像を何度も読み込む問題は解決しませんね。

ですから、staticを消してシングルトンパターンを使うことを先に考えなさい、という意味だったのでしょうか。
(例えばMAPクラスのインスタンスを1つにして、3つ分のレイヤを1つのCell cellにまとめる)
------
> 見るだけでなく実際に書いてください。

それでは、staticを使わずシングルトンを使う方向で書いてみようと思います。
時間がかかりそうなので、それでも分からないことがあれば日を改めて掲示板に書き込ませて頂こうと思います。

アバター
Dixq (管理人)
管理人
記事: 1662
登録日時: 14年前
住所: 北海道札幌市
連絡を取る:

Re: 静的メンバ変数から始まった細かい疑問

#8

投稿記事 by Dixq (管理人) » 9年前

> MAPクラスをシングルトンパターンにしても、
> レイヤを3つにするためにMAP map[3]として3つインスタンスを作るため、
> メンバ変数int tileDivとすると、tileDivは3つできてしまいます。

private:
int tileDiv[3][X];

としてはダメなんですか?
シングルトンのローカル変数を配列にするなり、持つクラスを多重化するなりすれば
シングルトンのインスタンスは一つでいいことになります。

もっと大きな括りで言うと
「Image」というシングルトンクラスがあって、そのImageがMapやPlayerやEnemyなどの画像データを保持してもいいんじゃないでしょうか。
Imageが一つでもMapを3つもたせればいいので親のインスタンスは一つでいいはずです。

moba
記事: 82
登録日時: 9年前

Re: 静的メンバ変数から始まった細かい疑問

#9

投稿記事 by moba » 9年前

> private:
> int tileDiv[3][X];

> としてはダメなんですか?
> シングルトンのローカル変数を配列にするなり、持つクラスを多重化するなりすれば
> シングルトンのインスタンスは一つでいいことになります。

Map map[3]ではなくて、Map mapにするということでしょうか。
それでしたら、Mapのメンバ変数Cell cellが問題でしたので、

変更前) Cell cell[ mapWidth * mapHeight ] //1つ分のレイヤ
変更後) Cell cell[ mapWidth * mapHeight * layerNum ] //3つ分

とすればいいでしょうか(No.7)。

tileDivはMAPのメンバ変数ですが、それをtileDiv[3][X]にするというのは
よく意味が分かりませんでした…
No.1で僕がコードの全文を貼っていなかったので、本当に紛らわしいと思います。
すみません。

> もっと大きな括りで言うと
> 「Image」というシングルトンクラスがあって、そのImageがMapやPlayerやEnemyなどの画像データを保持してもいいんじゃないでしょうか。
> Imageが一つでもMapを3つもたせればいいので親のインスタンスは一つでいいはずです。

シングルトンを使って、あらゆる場面で二度同じ画像を読み込まない仕組みを作る、
ということなのでしょうか(違ったらすみません)。

次にこの関係で質問する時があれば、書いてきたコードを全部貼ります。
ありがとうございました。

閉鎖

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