クラス型配列を同じクラス内関数の引数に使えますか?

このQ&Aのポイント
  • クラス型の配列を同じクラス内関数の引数に使用する方法について質問します。
  • 配列を関数内で参照できない場合、どのようにしてクラス内メンバの値を保持するかを知りたいです。
  • ゲーム作成中で、クラス型の配列を引数として渡して関数内でメンバの値を変更したいです。
回答を見る
  • ベストアンサー

クラス型配列を同じクラス内関数の引数に使えますか?

今ゲームを作成中です。クラス型の配列を引数で渡して その関数内でメンバの値を変えたいと思っています。 下記のような記述を試してみたのですがエラーは出ませんが 配列が関数内で参照できず思うようにいきません。 同じクラス内でクラス型の配列は使えないのでしょうか? その場合どのようにすれば配列でクラス内メンバの値を 保持すればよいでしょうか?ご回答お願いします。 #define Block_Max (100) Block* B Block* BB[] void main(){   for(int no=0; no < Block_Max; no++){     B->Block_Test(no,BB);   } } Block::Block_Test(int no,Block* BB[]){   BB[no]->B_Test_F = true; }

質問者が選んだベストアンサー

  • ベストアンサー
  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.3

このところ VisualStudio は使っていないので的を外しているかもしれませんが.... void Block::BlockTime(int no,Block* BB[],DWORD g_B_Time) にしろ void Block::Block_Add_End(int no,Block* BB[]) にしろ, 配列 BB はこれらの関数の仮引数になっています. つまり, これらの関数内で「BB」と書けば, それは Block* BB[BLOCK_ADD_MAX]; と定義した BB ではなく仮引数としての BB です. ということで, 「BBの中の要素数が表示されていた」という「別のクラス内」で「BB」が仮引数として使われているか確認してください. そちらで仮引数になっていないのであれば, 「仮引数になっているかどうか」が影響するのかもしれません. あと, 「プログラム上 (プログラムなりに) ちゃんと参照できている」んだけど「デバッガでは参照できていない」という可能性もありますね. この質問をするということは「関数内でメンバの値を変えたいと思ってプログラムを書いているにもかかわらずメンバの値が変わっていない」ということだと思うのですが, デバッガ以外でも「メンバの値がおかしい」ことは確認できていますか?

Uriaria
質問者

お礼

回答ありがとうございます! なるほど、そのまま実態を扱っている訳ではなく仮引数になっていたのですね。 「BBの中の要素数が表示されていた」そのBBの中を確認した場所は仮引数ではなく、 要素数が表示されていないところは仮引数でした。これが原因の元かもしれません。 原因についてなるべく自分で調べてみようと思います。的確な回答をありがとうございました。 関数内でメンバの値を変えたいと言うのはここの関数内で変えていて、書き忘れていました; やりたいことは落下するブロックが地面に触れて一定時間経過すると種類が変わるといった 処理を実装したいです。 for(int no=0; no<BLOCK_ADD_MAX; no++){ B->B_ChTime(no,BB,1000);  //1秒経過したら変化 if(BB[no]->B_ch_TF == true){     /*---------------------------------------      ここでB_ch_TFがtrueになっていないらしく      変化の処理が行われないのです;     ----------------------------------------*/         //変化等処理 } } /*--------------------------------------- ブロックチェンジタイム関数 ブロックが地面に触れてから変化 するまでの時間を計測する。 戻り値 なし 引数 番号、ブロック配列、変化の時間 ---------------------------------------*/ void Block::B_ChTime(int no,Block* BB[],DWORD B_ch_T){ if(BB[no]->B_ch_F == true){ /*----------------------------  ここまではブレークポイントで  止められ、通っていることが  確認できました。 ----------------------------*/ if(BB[no]->InitTime_ch == true){ BB[no]->LastTime_ch = timeGetTime(); BB[no]->InitTime_ch = false; } BB[no]->nowtime_ch = timeGetTime() - BB[no]->LastTime_ch; /*-------------------------------------------  ここから先にブレークポイント  を設けたところすべて関数の終わりに  位置が変更されうまくいかなくなっています; -------------------------------------------*/ if(BB[no]->nowtime_ch > B_ch_T && BB[no]->B_ch_TF == false){ if( BB[no]->B_ch_F == true ){ BB[no]->B_ch_TF == true; BB[no]->B_ch_F == false; } } } }//ブレークポイントの位置(デバッグ停止で元に戻る) class TimeControl{    public:      InitTime_ch   //計測開始      LastTime_ch   //計測した時間      nowtime_ch    //経過した時間 } class Block : public TimeControl {    public:      void B_ChTime(int no,Block* BB[],DWORD B_Ch_T);      bool B_ch_T;         //ブロックが地面に触れたか。      bool B_ch_TF; //ブロックが変化する時間を超えたか。       } デバッガ以外で確認する方法が思いつかず、if分で目的の値に指定して 中を通ったら― と思っているのですがうまくいきません; 一応B_ch_Fが通っているのでメンバの値全体がおかしいわけではないと思うのですが そうすると仮引数から値を書き換えていて問題がないことに・・・。

Uriaria
質問者

補足

すみません、自己解決しました。すごく単純なミスでした! BB[no]->B_ch_TF == true 代入の場所が==になっていておかしなことに なっていました!お恥ずかしい・・・。

その他の回答 (2)

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.2

「クラス型の配列」などどこにもいません (ある型とその型へのポインタとは全く別物) が.... さておき, こんな一部分だけ見せられてもどうにもならないので, そのような現象を起こす完全なプログラムを出してください. ああ, 「配列でクラス内メンバの値を保持する」ってのも, どういう意味で使っているのかわからん.

Uriaria
質問者

お礼

すみません。大事な部分が抜けていました; void Block::Block_Add_End(int no,Block* BB[]){   /*ここでブレークポイント    BBの中身をウォッチ式で    確認してみると要素が消えています;*/ BB[no]->B_add_F = false; BB[no]->B_add_TF = true; } 別のクラス内から参照した時はしっかりとBBの中の 要素数が表示されていたのですが何か関係があるのでしょうか?

Uriaria
質問者

補足

すみません。プログラムを人に見せたことがなくて; プログラムがなかったらわからない、当たり前でした。 ツールはVisualStudioを使っています #define BLOCK_ADD_MAX (100) TimeControl* g_Time; Block* B; Block* BB[BLOCK_ADD_MAX]; DWORD g_B_Time[] = {1.3, 1.8, 2.6, 3.5, 4.9, 6.3, 7.7, 8.9, 9.3, 10.2...}; //100個入ってます。 void Action::GameMain(void) { if(InitFlag){ InitGame(); } BlockWait(); void Action::InitGame(void){     g_Time = new TimeControl(); B = new Block(); for(int i=0;i < BLOCK_ADD_MAX; i++) BB[i] = new Block(); InitFlag = false; } /*-------------------------------- ブロックウェイト関数 ブロックを時間で出現させる。 戻り値 なし 引数  なし ---------------------------------*/ void Action::BlockWait(void){ for(int no=0;no<BLOCK_ADD_MAX;no++){ B->BlockTime(no,BB,g_B_Time[no]);//時間が経ったらブロックを出現 if(BB[no]->B_add_F == true){ if(no == 10) BB[no]->B_add_Gra = 1; //ブロックの落下速度増加 if(no == 20) BB[no]->B_add_Gra = 2; if(no == 30) BB[no]->B_add_Gra = 3; if( no == 40) BB[no]->B_add_Gra = 4; B->Block_Gravity_Set(no,true,BB); B->Block_Add_End(no,BB);             ... //その他画像、位置、当たり判定等をセット } } } /*------------------------------------------------- ブロックタイム関数 ブロックが出現するまでの 時間を計測する。 戻り値 なし 引数 配列番号、ブロックの配列、ブロック出現時間 --------------------------------------------------*/ void Block::BlockTime(int no,Block* BB[],DWORD g_B_Time){ if(BB[no]->InitTime == 1){ BB[no]->LastTime = timeGetTime(); BB[no]->B_add_T = g_B_Time; BB[no]->InitTime = 0; }     BB[no]->nowtime = timeGetTime() - BB[no]->LastTime; if(BB[no]->nowtime > BB[no]->B_add_T * 1000 && BB[no]->B_add_TF == false){ /*ここでブレーク  配列BBの中身を見ると  要素数が表示されていません・・・*/ BB[no]->B_add_F = true; //ブロック出現 } } /*-------------------------- タイムクラス ---------------------------*/ class TimeControl{ public: TimeControl(); ~TimeControl(); bool InitTime; DWORD LastTime; DWORD nowtime;       ... private: }; /*-------------------------   ブロッククラス --------------------------*/ class Block : public TimeControl { public: Block(); ~Block(); bool B_add_F; //ブロックが追加されたか。 bool B_add_TF; //ブロックが追加される時間が経過したか。 bool B_gra_F; //ブロックに重力がかかっているか。 int B_add_Gra;     //ブロックの重力を加速させるか。 void B_ChTime(int no,Block* BB[],DWORD B_ch_T); void BlockTime(int no,Block* BB[],DWORD g_B_Time); private: }; 「配列でクラス内メンバの値を保持する」と言うのは1個の配列で 時間などのメンバの値を持てたら便利かなと思って書きました。 紛らわしいことを書いてしまってすみません; 今やりたい処理があったのですがうまくいかず、 ブレークポイントを置いて調べようとしてみたところ勝手に場所が変わってしまいます。 その現象が起こる共通の部分がクラス内でクラス型配列を使っている部分でしたので もしかしたらと思って質問しました。

回答No.1

このソースだけだと、BもBBもポインタ変数が定義されているだけで、クラスのインスタンスがありません。 int* p; *p=1; がコンパイルエラーにはならないけど正しく動作しないのと同様です。 あと、グローバル変数を使うなら、同じ変数名を関数の引数に使用するのはやめた方がいいですよ。

Uriaria
質問者

お礼

すみません。インスタンスの生成を書き忘れていました; アドバイスありがとうございます!できるだけ引数では別の変数名を使うようにしようと思います。

関連するQ&A

  • 2次元配列を引数とする関数について

    2次元配列を引数とする関数について 私は今、2次元配列を引数とする関数の表を作るという課題に取り組んでいます。 条件として、int a[数字][数字]={{1,2,3...}}という配列の宣言と同時の初期化は使わず、 関数内で表の値を代入し、値を表示する関数を作り、事実上二つの関数を作るというものです。 私は以下のようなプログラムを作り、動かしましたが、[数字][数字]=********のような本来 あるべき実行結果とは異なる数字の羅列が出てきてしまいました。 ↓ #include <stdio.h> void func(int a[][6]); void fund(int b[4][6]); void main(void) { int a[4][6]; fund(a); func(a); } void func(int a[][6]) { int i,j,b[4][6]; fund(b); for(i=0;i<4;i++)        { for(j=0;j<6;j++) { printf("a[%d][%d]=%d\n",i,j,a[i][j]); printf("\n"); } } } void fund(int b[4][6]) { int i,j; for(i=0;i<4;i++) { for(j=0;j<6;j++)          { scanf("b[%d]*[%d]=%d\n",&i,j,b[i][j]); } } } 本来の実行結果 1 2 3 4 5 6 2 4 6 8 10 12 3 6 9 12 15 18 4 8 12 16 20 24 紙にも書いて何回も見直しましたが、どこがおかしいのかわかりませんでした。 どうすれば良いのでしょうか? 何か良いアドバイスをよろしくお願いします。

  • 引数に二重配列のある関数について

    void calc(int *a,int b,int c){ a[0]=b+c; a[1]=b-c; } void main(void){ int x[2]; int y=2,z=5; calc(x,y,z); printf("x[0]=%d,x[1]=%d\n",x[0],x[1]); } 上のように引数が普通の配列の関数ならできるのですが, 引数が下のような多重配列になるとエラーが出てしまいできません。 void keisan(int **a,int b,int c){ a[0][0]=b+c; a[0][1]=b-c; a[1][0]=b*c; a[1][1]=b/c; } void main(void){ int x[2][2]; keisan(x,6,2); printf("x[0][0]=%d,x[0][1]=%d\n",x[0][0],x[0][1]); printf("x[1][0]=%d,x[1][1]=%d\n",x[1][0],x[1][1]); } 引数に多重配列を使った場合の関数の作り方について教えてください. お願いいたします.

  • C#で、引数にクラスの配列の参照パラメータを渡したい

    C#始めて3日目ですが、そろそろ挫折しそうです。 以下のクラス class Test{ int num; public Test(){ num = 0 }; ~Test(){}; public void set(int n){ num = n; } public int get(){ return num; } } があり、 void kakikae(Te [] t){ for(int i =0; i < 10; i++){ t[i].set(i); } } Test [] test = new Test[10] = { new Test, new Test, new Test, new Test, new Test, new Test, new Test, new Test, new Test, new Test }; kakikae(test); とした時に、test[0]からtest[9]まで 1,2,3,4,5,6,7,8,9 の値が入っている事がしたいのです。 要は、クラスの配列のポインタを渡して、相手側の関数で書き方内容が、関数から戻った時も値渡しでなく 参照渡しのように値が変わって戻ってきて欲しいです。 配列の仕組み、クラスの仕組み、パラメータの仕組みが 分からず、ここから進みません。 1から勉強できるC#の参考書も探しています。

  • 多次元配列のポインタ渡し

    C++を使用しています。 多次元配列を関数の引数として渡したいとき、関数側では void A::Func(int a[10][20][30])~ 呼びだし側では Finc(a); とやればいいのはわかります。 お聞きしたいのは、仮引数として呼び出された配列(上でいうa)をクラスのメンバ変数として保持したい場合の方法です。 aは先頭アドレスなのでそこを差すポインタを受ければいい、っていうことはわかりますが、 この方法ですと、受けたメンバ変数が配列みたいに[]を使ってアクセスできません。 (メンバ変数のポインタは配列じゃないから当然ですよね) これを通常の配列みたいに扱えるようにするにはどうしたらいいでしょうか。

  • 引数が配列のときの関数内でのsizeofについて

    こんにちは. Cを勉強している最中に疑問にあったことを質問させていただきます.以下のプログラムで配列myarrayの中の最大のメンバーを見つけるプログラムです.コメントアウトしてある //int ary_size = sizeof(myarray)/4; をグローバル変数で定義するとうまく最大の数を見つけてくれるのですが, 関数の中で int ary_size = sizeof(ary)/4; と定義するとうまくいきません.そこで,以下の printf("The size of the ary is %d\n",ary_size); という表示を追加したところ,ary_size = 1となっていることが分かりました. なぜそうなるのでしょう?関数の引数はint ary[]の配列なので,sizeof(ary)でaryがメモリ中で占めるバイト数が得られるんじゃないんですかね?ちなみに私の環境ではsizeof(int)は4バイトなので int ary_size = sizeof(ary)/4; と割る4で配列のメンバーの数を求めています. 初心者の質問ですみませんがよろしくお願いします. #include <stdio.h> #include <Windows.h> int myarray[] = {1,2,3,4,5,6,7,2}; int FindMax(int ary[]); //int ary_size = sizeof(myarray)/4; int main() { int max; max = FindMax(myarray); printf("The maximum value is %d\n",max); Sleep(2000); return(0); } int FindMax(int ary[]) { int ary_size = sizeof(ary)/4; int i; int max; max = ary[0]; for(i=1;i<ary_size;i++) { if(ary[i]>max) { max = ary[i]; } } printf("The size of the ary is %d\n",ary_size); return(max); }

  • できているとは、思うのですが。ポインタの配列を

    コンパイラではちゃんと動いてます。 1 2 3 0 1 2 3 という具合です。 気になるのは、printarrayの部分が正しいのか、ちょっと悩んでいます 問題としては main関数では0の値を読み込むまで最大99(MAX-1)個の値を配列 xに読み込んでいる。引数のポインタからの値を、値が0になるまで すべて1行に1つづつ画面に出力する関数printarray()を作成し、 プログラムを完成せよ。 引数はアドレスとして受け取る事。(配列としてでなく) フォーマットは、 "%d¥n" とする。(余計な出力はしない事。) (0は出力しない。) main内部を変更してはならない。 以下がソースです。 ご指摘よろしくお願いします。 #include <stdio.h> #define MAX 5 void printarray(int *); int main() { int x[MAX], i; int *p; x[MAX-1] = 0; for (i = 0, p = x; i < MAX-1; ++i, ++p) { scanf("%d", p); if (*p == 0) { break; } } printarray(x); return 0; } void printarray(int *a) { int i,*p; for(i = 0, p = a; i < MAX-1; ++i,++p) { if(*p == 0){ // continue; break; }else{ printf("%d\n", *(a+i)); } } }

  • 関数に配列を渡すときの質問です

    関数に配列を渡したいんですがこのソースが問題ないか見てください。 #include<stdio.h> #define N 10 #define M 20 int sig(int X[],int x); main() { int a[N],b[M],i,x,y; for(i=0 ; i<N ; i++){ a[i]=i; } for(i=0 ; i<M ; i++){ b[i]=i; } x=sig(a,N); y=sig(b,M); } int sig(int Z[],int x){ int i,k; k=0; for(i=0 ; i<x ; i++){ k=k+Z[i]; } return k; } ソースは以上です。 1つのソースの中でa[N]とb[M]のように違う数の 配列があるんですが、その配列全部(0~N-1、0~M-1)とかを足してくれる(シグマ)関数を作りたいんですが、Z[]と配列の数を指定しなくてもちゃんと動いてくれるんでしょうか?関数のほうの int x で配列の数を指定するようにしています。 自分でテストした限りではちゃんと動いているようなんですが、間違ってるようなら指摘お願いします。

  • Java クラスを使ったソート

    Javaで隣接交換法を用いて配列dataを昇順に並び替え、出力するプログラムを作成する。 ただし、ループ処理には、int型の変数は使わず、以下のCounterクラスを使用する。 という課題が出て、とり組んでみたのですが所々よく分からないので、お力添えしていただければと思います。 課題には下記のような条件が書いてありました。 配列data={54,76,32,89,45,11,8,54,29,67}; [クラス] Counter [インスタンス変数] int型の値を保持するcount [コンストラクタ] 引数で渡された値を初期値としてインスタンス変数に設定する。 引数を省略された場合、ゼロを設定する。 [メソッド] increment 値に1加算する decrement 値に1減算する compareTo 以下の処理を行う Counterの保持している値が引数に指定された値と 等しい場合、値0を返す。 Counterの保持している値が引数に指定された値より 小さい場合、0より小さい値を返す。 Counterの保持している値が引数に指定された値より 大きい場合、0より大きい値を返す。 get Counterの保持している値を添え字として、 引数で渡された配列の要素を取得します。 set Counterの保持している値を添え字として、 第1引数で渡された配列に第2引数で渡された値を設定します。 以下組んだものです。 ---- class Counter { int count = 0; Counter(int count) { this.count = count; } Counter() { this.count = 0; } public int get(int[] data) { return this.count; } public void set(int[] data, int count) { this.count = count; } public void increment() { this.count = count + 1; } public void decrement() { this.count = count - 1; } public int compareTo() { return count; } } public class Lesson09 { public static void main(String args[]) { Counter counter = new Counter(0); int[] data = {54, 76, 32, 89, 45, 11, 8, 54, 67}; counter.get(data); counter.set(data, 0); } } ---- とりあえず、compareToとsetとgetの部分をどう記述していいのかがよく分かりません。 よろしくお願いします。

    • ベストアンサー
    • Java
  • define で 配列

    #defineで配列を定義したいのですがこのようなことは可能でしょうか? ヘッダファイル(test.h)で #define MAX (2) int A[MAX]={20,30}; ソースファイルで #include <stdio.h> #include "test.h" int main(){ int i; for(i=0;i<MAX;i++){ printf("A[%d]=%d\n",i,A[i]); } return 0; } とやれば出来るのですが、このヘッダファイルを複数のソースで参照すると 多重定義であるとおこられてしまいます。 #defineで #define A[MAX] {20,30} のように配列を定義する方法は存在するのでしょうか? どなたか良い方法を御存じの方、ご教授お願いします。

  • IntArrayクラスのプログラムを組んでいるのですが・・・

    javaプログラミングで以下の内容を満たす、IntArrayクラスを作成しています。 ・インスタンス変数  int型の配列data ・コンストラクタ  (1)int型の配列を受け取り、そのコピーを内部的に保持する  (2)第1引数で指定された要素数を持つ配列を確保し、全ての要素に初期値として第2引数で指定された値をセットする  (3)第1引数で指定された要素数を持つ配列を確保し、全ての要素に初期値としてゼロをセットする ・メソッド  (1)sort   内部的に保持している配列を、引数の値がtrueであれば昇順、falseであれば降順にソートする  (2)length   IntArrayが保持している配列の要素数を取得する  (3)getElement   引数に指定された要素番号の値を取得する  (4)setElement   第1引数に指定された要素番号に第2引数で指定された値を格納する   (5)getArray   IntArrayが保持している配列のコピーを取得する 実際にプログラムを組んでみたのですが、※の部分が冗長だと指摘を受けました。 しかしどのように修正したらよいかわかりません。 どうかアドバイスなどをよろしくお願いいたします。 package java_Lesson; import java.util.Arrays; /** * int型の配列dataの要素を取得、あるいは操作するクラス */ class IntArray { private int[] data; /** * int型の配列を受け取り、そのコピーを内部的に保持する * * @param args コピー元となる配列 */ IntArray(int[] args) { data = (int[])args.clone(); } /** * 第1引数で指定された要素数を持つ配列を確保し、 * 全ての要素に初期値として第2引数で指定された値をセットする * * @param arg1 配列の要素数 * @param arg2 配列の初期値 */ IntArray(int arg1, int arg2) { this(arg1); /* ※ */ for (int index = 0; arg1 > index; index ++) { data[index] = arg2; } } /** * 第1引数で指定された要素数を持つ配列を確保し、 * 全ての要素に初期値としてゼロをセットする * * @param arg 配列の要素数 */ IntArray(int arg) { data = new int[arg]; } /** * 内部的に保持している配列を昇順、あるいは降順にソートする * * @param arg trueであれば昇順、falseであれば降順にソート */ void sort(boolean arg) { Arrays.sort(data); if (arg) { return; } int array = data.length - 1; for (int index = 0; array > index; index ++, array --) { int temp = data[index]; data[index] = data[array]; data[array] = temp; } } /** * IntArrayが保持している配列の要素数を取得する * * @return 配列の要素数 */ int length() { return data.length; } /** * 引数に指定された要素番号の値を取得する * * @param arg 返す要素の要素番号 * * @return 配列dataの要素番号argの値 */ int getElement(int arg) { return data[arg]; } /** * 第1引数に指定された要素番号に第2引数で指定された値を格納する * * @param arg1 値を格納する要素番号 * @param arg2 配列に格納する値 */ void setElement(int arg1, int arg2) { data[arg1] = arg2; } /** * IntArrayが保持している配列のコピーを取得する * * @return 配列dataのコピー */ int[] getArray() { return data.clone(); } }

    • ベストアンサー
    • Java