ページ 11

C++でのグローバル変数的な変数の定義の仕方について

Posted: 2010年7月21日(水) 12:32
by かぶと
こんにちは、かぶとと申します。
今回はC++について知りたい事があります。

C++でクラスを2つ作ったのですが
片方のクラス(A)内の関数で0を代入した変数が
そのクラスA内の別の関数では0が代入されてなくて
マイナス8万幾つと言う数字が入っていました。

また、もう片方のクラスBの方に
クラスAの変数を引っ張って来て使おうと思っても
上手く行きません。

クラス間や関数間での変数のやり取りは
どの様にしたら宜しいでしょうか。

Re:C++でのグローバル変数的な変数の定義の仕方について

Posted: 2010年7月21日(水) 12:43
by シエル
コードを提示して下さい。

Re:C++でのグローバル変数的な変数の定義の仕方について

Posted: 2010年7月21日(水) 13:55
by かぶと
すいません、ゲームに組み込んであって
なかなか簡単に再現が出来ません。

簡単に言うとC言語で言う所の
exturnはC++ではどの様にやるんでしょうか。
ソースを分けて作り始めてからこの状態です。

Re:C++でのグローバル変数的な変数の定義の仕方について

Posted: 2010年7月21日(水) 14:55
by softya
同様の問題があるソースコードを作ることは難しいと思えませんので、同じ問題が出る簡潔なコードを新たに作ってみてみらえますか。それが、いちばんの早道だと思います。

Re:C++でのグローバル変数的な変数の定義の仕方について

Posted: 2010年7月21日(水) 18:54
by DVDM
>>かぶとさん
[color=gray>> 片方のクラス(A)内の関数で0を代入した変数が…[/color]
その原因が解っているクラスのソースだけでも提示することはできないでしょうか。
やはりソースの提示が出来ないと答え辛いですが、なんとなくで書いてみますので
見当はずれでしたら御免なさい。

・変数を定義しているだけで、初期化を行っていない
・初期化を行うよりも前に、関数でその変数を使用している
・メンバ変数と同じ名前の変数が、関数内で初期化されていないローカル変数として使用されている
・0を入れた変数名が間違っている
・初期化されていない別の変数が、問題となっている変数に代入されている

くらいしか思い浮かびませんでした。
その変数がどこで初期化され、どこで使用されているかの確認が必要だと思います。


[color=gray>> exturnはC++ではどの様にやるんでしょうか。[/color]
C++ でも extern は使用できますがそれではいけないのでしょうか。
それ以外なら、継承を使用したり、使用したいクラスで定義したり、
ポインタや参照で渡して使用していく感じでしょうか…。

Re:C++でのグローバル変数的な変数の定義の仕方について

Posted: 2010年7月21日(水) 18:56
by かぶと
下記に書いたのと同じ状態です。
PosXとPosYが無い、と出てしまいます。
どうしたら良いでしょう。


────────────────

//// Player.h ////

class Player{

public:
int PosX;
int PosY;
void Dainyu();
};

────────────────

//// Player.cpp ////

#include"Player.h"

void Dainyu(){

PosX=100;
PosY=100;

}

────────────────

//// Main.cpp ////

#include<iostream.h>
#include"Player.h"

int main(void){

Player PL;

cout << PL.PosX << endl;

return 0;

}

────────────────

※下記は、上記を実行した際に表示されるエラー※

--------------------構成: Test - Win32 Debug--------------------
コンパイル中...
Player.cpp
C:~Test\Player.cpp(5) : error C2065: 'PosX' : 定義されていない識別子です。
C:~Test\Player.cpp(6) : error C2065: 'PosY' : 定義されていない識別子です。
cl.exe の実行エラー

Test.exe - エラー 2、警告 0

Re:C++でのグローバル変数的な変数の定義の仕方について

Posted: 2010年7月21日(水) 18:59
by かぶと
>シエルさん、softyaさん

すいませんでした。
コードを作りました。


>DVDMさん

少ない情報で推理してくれてありがとうございます。
原因になっていると思われる部分の説明を
一行ずつ調べながら読んでいます。

コードが作れたので、出しました。

Re:C++でのグローバル変数的な変数の定義の仕方について

Posted: 2010年7月21日(水) 19:00
by シエル
void Player::Dainyu(){

PosX=100;
PosY=100;

}

こうしたらどうですか?

Re:C++でのグローバル変数的な変数の定義の仕方について

Posted: 2010年7月21日(水) 19:01
by Poco
> 下記に書いたのと同じ状態です。
> PosXとPosYが無い、と出てしまいます。
> どうしたら良いでしょう。
>
>(略)
>
> void Dainyu(){
>
> PosX=100;
> PosY=100;
>
> }
>

関数Dainyu()から見える場所にPosX、PosYがありません。
やりたいことは↓のようなことですか?

void Dainyu(Player& p){

p.PosX=100;
p.PosY=100;

}

----追記
Dainyu()ってPlayerクラスのメンバ関数だったんですね。。
シエルさんが提示されたコードが正しいです。
私のは忘れてください。

#最近、コードちゃんと読めてないなぁ。。
画像

Re:C++でのグローバル変数的な変数の定義の仕方について

Posted: 2010年7月21日(水) 19:25
by dic
//// Player.cpp //// 

#include"Player.h" 

void Dainyu(){ 
     
    PosX=100; 
    PosY=100; 
     
}
class Player 指定するの忘れてませんか?

void Player::Dainyu()

ではないでしょうか?


//------------------------------
かぶってますね^^;
画像

Re:C++でのグローバル変数的な変数の定義の仕方について

Posted: 2010年7月21日(水) 19:34
by かぶと
void Player::Dainyu()

にしたら出来ました。
どうもありがとうございます。
テストの方は完了しました。
皆様どうもありがとうございました。

しかし、ゲームのメインの方のコードが
上手く出来ません。
やっぱり恥を捨ててアップロードします。
画像

Re:C++でのグローバル変数的な変数の定義の仕方について

Posted: 2010年7月21日(水) 19:44
by DVDM
>>かぶとさん
[color=gray>> ゲームのソースはアップローダーなどで
> 全部載せても大丈夫ですかね。[/color]
アップロードできるのであればそうされた方がいいと思います。

Re:C++でのグローバル変数的な変数の定義の仕方について

Posted: 2010年7月21日(水) 19:56
by かぶと
http://firestorage.jp/download/8baf2661 ... be8255cf33

ゲームソースです。

CameraX
CameraY

の、Playerの関数内の定義の仕方が分かりません。
それ以外にもゴチャゴチャしてます。

何かこうした方が良いと言うのがあったら
宜しくお願いします。

Re:C++でのグローバル変数的な変数の定義の仕方について

Posted: 2010年7月21日(水) 20:53
by シエル
Fieldクラスのインスタンスを作って、呼び出せばいい。

Field test;

test.CameraX=100


みたいな感じ。

Re:C++でのグローバル変数的な変数の定義の仕方について

Posted: 2010年7月21日(水) 21:07
by DVDM
>>かぶとさん
ソースを拝見させて頂きました。
DXライブラリが手元になく、コンパイルはしていませんので間違いがあったら御免なさい。
[color=gray>
void Player::GraphDraw(){

    // カメラのXとYを外部から引っ張って来る
    [color=red>int CameraX=0;
    int CameraY=0;[/color]

    // プレイヤー描画
    DrawGraph(PlayerX-CameraX, PlayerY-CameraY, GHandle[graphnumbe[/url], TRUE);

    DrawFormatString(0,  0, GetColor(255, 0, 0), "PlayerX=%d",CameraX);
    DrawFormatString(0, 20, GetColor(255, 0, 0), "PlayerY=%d",CameraY);
}
[/color]
初期化されていない変数を使用されているのが原因だと思います。
int CameraX, CameraY はローカル変数のため、書いただけでは初期化されておりません。

int CameraX=0;
int CameraY=0;
…と初期化しておけばとりあえず大丈夫ですが、多分やりたいことと違うような気がします。

この CameraX, CameraY は、Field クラスにある CameraX, CameraY とは別物と考えて宜しいのでしょうか?
もし、 Field クラスのものを使用したければ 引数で貰ってきたり、
クラス内で Field クラスを定義しアクセスする必要があります。

[color=gray>
class Player{

        int GHandle[100];
        int count;
        short graphnumber;
        short Action;
        [color=red>int PlayerX;
        int PlayerY;[/color]

    public:
        void Init();
        void Animetion();
        void GraphDraw();
        int JoyStick();
};
[/color]
また、Player クラスにあるメンバ変数 PlayerX, PlayerY が public でしたので、
private にしておいた方がいいと思います。
同様に、Field クラス内の CameraX, CameraY も private にしておいた方がいいと思います。
(public がいいのであればそのままで構いませんが…。)


[color=gray>
void Field::Scroll(){

    // 代入変数
    int blank=200;

    // フィールドクラス定義
    Field FD;
    Player PL;
    [color=red>PL.Init();[/color]

    // 左端
    if((PL.PlayerX-CameraX)<blank){
        CameraX=FD.Limit(PL.PlayerX-blank, 0, mapWidth-640);
    }

    // 右端
    if((640-blank)<(PL.PlayerX-CameraX)){
        CameraX=FD.Limit(PL.PlayerX+blank-640, 0, mapWidth-640);
    }
}
[/color]
やはり、こちらでも初期化されていないのが原因かと思われます。
Player PL;
の次の行に PL.Init(); と入れてやればとりあえず大丈夫です。


[color=gray>
void Field::Init(){
    GHandle=0;
    CameraX=0;
    CameraY=0;

    [color=red>mapWidth = 100;
    mapHeight = 100;[/color]
    GHandle=LoadGraph("BMP/Field.bmp");
    GetGraphSize(GHandle, &mapWidth, &mapHeight);
}
[/color]

メンバ変数である mapWidth, mapHeight の初期化も行われておりませんでしたので
とりあえず 100 という値を入れさせて頂きました。



Init 関数を呼ぶのが面倒だと感じるのであれば
コンストラクタを定義してみるのも一つの手かもしれません。
例えば、Player クラスの場合:

[color=gray>
- Player.h -

class Player{

        int GHandle[100];
        int count;
        short graphnumber;
        short Action;
        int PlayerX;
        int PlayerY;

    public:
        [color=red>// コンストラクタ
        Player()
        {
            this->Init();
        }[/color]
    (以下略)
[/color]

コンストラクタを追加することで Player PL; と定義した時に
コンストラクタで Init を呼んでくれるため自分で呼ぶ必要がなくなります。

かぶとさんが期待されている結果が私には解らなかったので、とりあえずという表現をしております。
これで八万なんぼという結果はなくなると思うのですが如何でしょうか。

Re:C++でのグローバル変数的な変数の定義の仕方について

Posted: 2010年7月22日(木) 07:53
by naohiro19
this->PosXでprivate属性のついた変数にアクセス可能です。

Re:C++でのグローバル変数的な変数の定義の仕方について

Posted: 2010年7月22日(木) 08:56
by かぶと
thisポインタとコンストラクタで初期化を調べています。
DVDMさんとても丁寧な解説で助かります。

ただ、説明がたりな過ぎて申し訳ありませんでしたが
スクロール関数は画面をスクロールする度に呼び出したい関数なので
その中で初期化は出来ないかも知れません。

Field FD;でFD.CameraXに変えたらエラーが出てしまいました。

CameraX、CameraYと言う変数は、本当は
もっと広い範囲で使える様にしてみたいのですが
変数の範囲がどのくらいに出来るかと言うのも
良く分かりません。

取り合えず基本を勉強した方が良いでしょうか。

Re:C++でのグローバル変数的な変数の定義の仕方について

Posted: 2010年7月22日(木) 10:31
by DVDM
>>かぶとさん
[color=gray>> スクロール関数は画面をスクロールする度に呼び出したい関数なので
> その中で初期化は出来ないかも知れません。 [/color]
ということは、Field::Scroll 関数内の下記処理
[color=gray>if(([color=red>PL.PlayerX[/color]-CameraX)<blank){
    CameraX=FD.Limit(PL.PlayerX-blank, 0, mapWidth-640);
}[/color]

では、PL.PlayerX は初期化されていない状態で使われることになるので望む結果にはならないと思います。
これは一例ですが、PlayerX, PlayerY の値を引数で貰ってくるというのはどうでしょうか。

void Field::Scroll(int PosX, int PosY){ ~処理~ }
プレイヤーの座標をこのように受け取り、関数内で使用していこうという流れです。


[color=gray>> Field FD;でFD.CameraXに変えたらエラーが出てしまいました。 [/color]
どういったエラーでしょうか?
これも、CameraX が初期化されていないのが原因ではないでしょうか。


[color=gray>> 変数の範囲がどのくらいに出来るかと言うのも
> 良く分かりません。 [/color]
例えば、Field::Scroll 関数を一例に上げますと
[color=gray>
void Field::Scroll(){

    // 代入変数
    int blank=200;

    // フィールドクラス定義
    Field FD;
    Player PL;
  (以下略)
[/color]

FD, PL の寿命はこの Scroll 関数を抜けるまでということになります。
「変数 スコープ c」なんかで検索をかけると色々見つかると思います。
参考URL:http://www.geocities.jp/ky_webid/c/022.html


[color=gray>> 取り合えず基本を勉強した方が良いでしょうか。[/color]
もし関数について「引数」「戻り値」などが解っていないとこの先辛いと思います。
不安だと感じたらすぐに勉強してみましょう。

一番気になったのが初期化忘れでしたので、
まずは変数を初期化し、その後で使用するというのを心掛けてみてはいかがでしょうか。
(個人的にはコンストラクタでメンバ変数を初期化する方が便利だと思います)

かぶとさんが希望する処理を一つずつ整理し、
どのような処理を行いたいのか、その為にはどのクラスに変数・関数を持たせるかなどを考えて行けば
スッキリするのではないでしょうか。

「こんなことをこういう感じで行いたい」と具体的に示して頂ければ
アドバイスも集まりやすくなると思います(多分…)。

Re:C++でのグローバル変数的な変数の定義の仕方について

Posted: 2010年7月22日(木) 13:29
by かぶと
DVDMさんありがとうございました。
スコープと言うのも調べています。

結局、基本的な事が分かっていなかったので
基本を勉強してからもう一度頑張ろうと思います。

今回は解決する事にします。