ページ 11

動的2次元配列(new)についてお聞きしたいことが…。

Posted: 2013年8月09日(金) 10:07
by TJJ
現在、私はDXライブラリでRPGをつくってます。マップを管理する際にどうしてもマップデータを動的確保して静的領域に余裕を持たせたいと思ってます。
しかし、以下の内容でプログラムを書き進めることができません。

コード:

class Map{
	int **map;
	int old_limit_h;//動的map[][] 解放用 縦幅
public:
	static void create_map(int,int);//Map variable
	static int view_map(int,int);
	static void input_map(int,int,int);//w,h,data
	static void destruct_map();//Destructing map variable
};

void Map::create_map(int h,int w){
	map = new int*[h]; //<- ここでmapの参照エラーが出てきて困ってます!!以下のmapも参照エラーを起こしてます。
	for (int i = 0; i < h; i++) {
		map[i] = new int[w];
	}
	old_limit_h = h; //<- mapだけではなく old_limit_hも参照エラーを起こしてます。
}

int Map::view_map(int h,int w){
	return (map[h][w]);
}

void Map::input_map(int h, int w, int data){
	map[h][w] = data;
}

void Map:destruct_map(){
	for (int i = 0; i < old_limit_h; i++) {
    delete[] map[i];
	}
	delete[] map;
}
開発環境 VC++ 2008 Express Edition
エラーの内容は

静的でないメンバ 'Map::map' への参照が正しくありません。
静的でないメンバ 'Map::old_limit_h' への参照が正しくありません。
'Map::map': 関数呼び出しには引数リストがありません。メンバへのポインタを作成するために '&Map::map' を使用してください
配列または、ポインタでない変数に添字が使われました。

という内容です。

本やほかのサイトで文法について調べましたが原因が分かりません。

動的確保の仕方が間違っているのでしょうか? ご回答お願い致します。


前回、私の疑問を解決してくださった方、この質問をご覧になっていらっしゃらないかと思いますが、ここでお礼を申し上げます。

Re: 動的2次元配列(new)についてお聞きしたいことが…。

Posted: 2013年8月09日(金) 10:15
by softya(ソフト屋)
2次元配列なると解放とか読み込みとか要素へのアクセスとか色々と面倒なので通常は縦x横の1次元配列を使います。
クラスに隠蔽するのなから中の動作が隠せますからね。
x * 縦サイズ + y
で配列の添字は計算出来ます。
と言うことでいかがでしょうか?

Re: 動的2次元配列(new)についてお聞きしたいことが…。

Posted: 2013年8月09日(金) 10:18
by beatle
Map::mapはインスタンス変数といって、Mapクラスをインスタンス化しないと使えない変数です。
一方でMap::create_mapは静的(=static)関数ですので、Mapクラスをインスタンス化せずに使える関数です。

存在しない変数に書き込もうとしていますのでエラーが出ています。

解決策:
Map::mapをクラス変数にするか、Map::create_mapを静的でない関数にします。

Re: 動的2次元配列(new)についてお聞きしたいことが…。

Posted: 2013年8月09日(金) 10:22
by softya(ソフト屋)
グローバルなクラスにしたいなら、シングルトンを使われては?
staticは面倒でしょう。

Re: 動的2次元配列(new)についてお聞きしたいことが…。

Posted: 2013年8月09日(金) 10:23
by みけCAT
softya(ソフト屋) さんが書きました:2次元配列なると解放とか読み込みとか要素へのアクセスとか色々と面倒なので通常は縦x横の1次元配列を使います。
クラスに隠蔽するのなから中の動作が隠せますからね。
x * 縦サイズ + y
で配列の添字は計算出来ます。
と言うことでいかがでしょうか?
最近自分が思いついた方法では、
1.情報を入れる1次元配列(要素数は縦サイズ×横サイズ)とポインタを入れる1次元配列(要素数は縦サイズ)の2本を確保
2.ポインタを入れる1次元配列のi番目(i=0,1,...,縦サイズ-1)の要素に情報を入れる1次元配列の(i*横サイズ)番目の要素のポインタを代入
3.ポインタを入れる1次元配列を元の情報の2次元配列として利用する
というものがあります。
これで確保の手間の少なさとアクセスの便利さ(掛け算を書かず、普通の2次元配列のように書ける)を両立できると思います。

Re: 動的2次元配列(new)についてお聞きしたいことが…。

Posted: 2013年8月09日(金) 10:27
by zxc
  Mapクラスのメンバ関数は静的ですが、メンバであるmapやold_limit_hは静的ではない(staticで修飾されていない)ですよね。
  main関数や他の関数でどう呼び出しているかわからないので推測ですが、Mapクラスの実体を作らずに関数を使用しようとしたため、実体の無いMap::mapやMap::old_limit_hをその関数で利用することができないと言う旨のエラーではないでしょうか。次からはエラーの番号(と言って良いのか分かりませんが)もぜひ載せてください。

  それとよくわかりませんが、もし質問されてその疑問が解決したにもかかわらず、適切な返答とトピックの解決をされていないのであれば、ここではなく、そのトピックで対応すべきことだと思います。
  

Re: 動的2次元配列(new)についてお聞きしたいことが…。

Posted: 2013年8月09日(金) 11:57
by softya(ソフト屋)
あれ? 過去に質問が残っているんですね。
調べみてました。

「プログラミングの上達方法について • C言語交流フォーラム ~ mixC++ ~」
http://dixq.net/forum/viewtopic.php?f=3&t=12860
「ゲームプログラミングでフローチャートは書くべきですか? • C言語交流フォーラム ~ mixC++ ~」
http://dixq.net/forum/viewtopic.php?t=9586&p=77308
これですね。

質問はからなず解決させて、どのように解決したか、あるいはどのように参考なったか詳細にお書きください。
http://dixq.net/board/board.html
後から見た他の人の参考になるようにお願いします。

Re: 動的2次元配列(new)についてお聞きしたいことが…。

Posted: 2013年8月09日(金) 17:33
by ISLe
ポインタのポインタによる2次元配列では、
・横幅の加算で縦に移動できない
・静的領域にマップデータを配置できない(ヒープを余分に消費する)
という点が不便です。

アクセサを用意したほうが縦横の順番を気にする必要もなくなりますし。

Re: 動的2次元配列(new)についてお聞きしたいことが…。

Posted: 2013年8月10日(土) 04:27
by かずま
static の意味を全く理解されていないようですね。
勉強してください。
プログラムですが、次のように書けばいいのでは?

コード:

class Map {
    int **map;
    int old_limit_h;
    Map(int w, int h);
    ~Map();
public:
    static Map *create_map(int w, int h);
    int view_map(int w, int h);
    void input_map(int w, int h, int data);
    void destruct_map();
};
 
Map::Map(int w, int h) : map(0)
{
    map = new int*[h];
    for (int i = 0; i < h; i++) map[i] = new int[w];
    old_limit_h = h;
}
 
Map::~Map()
{
    if (map) {
        for (int i = 0; i < old_limit_h; i++) delete[] map[i];
        delete[] map;
        map = 0;
    }
}

Map *Map::create_map(int w, int h) { return new Map(w, h); }
int  Map::view_map(int w, int h) { return map[h][w]; }
void Map::input_map(int w, int h, int data) { map[h][w] = data; }
void Map::destruct_map() { delete this; }

#include <iostream>
int main()
{
    Map *p = Map::create_map(1920, 1080);
    p->input_map(640, 480, 123);
    std::cout << p->view_map(640, 480) << std::endl;
    p->destruct_map();
}

Re: 動的2次元配列(new)についてお聞きしたいことが…。

Posted: 2013年8月10日(土) 04:39
by かずま
コンストラクタの : map(0) と、
デストラクタの if (map) と map = 0; は無意味でした。
削除してください。

Re: 動的2次元配列(new)についてお聞きしたいことが…。

Posted: 2013年8月10日(土) 09:07
by usao
オフトピック
複製行為への対策も欲しいですね

Re: 動的2次元配列(new)についてお聞きしたいことが…。

Posted: 2013年8月10日(土) 19:18
by かずま
static を使わないなら、次のようになります。

コード:

class Map {
    int **map;
    int old_limit_h;
public:
    void create_map(int w, int h);
    int view_map(int w, int h);
    void input_map(int w, int h, int data);
    void destruct_map();
};
 
void Map::create_map(int w, int h)
{
    map = new int*[h];
    for (int i = 0; i < h; i++) map[i] = new int[w];
    old_limit_h = h;
}
 
void Map::destruct_map()
{
    for (int i = 0; i < old_limit_h; i++) delete[] map[i];
    delete[] map;
}

int  Map::view_map(int w, int h) { return map[h][w]; }
void Map::input_map(int w, int h, int data) { map[h][w] = data; }

#include <iostream>
int main()
{
    Map obj;
    obj.create_map(1920, 1080);
    obj.input_map(640, 480, 123);
    std::cout << obj.view_map(640, 480) << std::endl;
    obj.destruct_map();
}