[C++]別ファイルでクラスが未定義だといわれる

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
五穀豊穣

[C++]別ファイルでクラスが未定義だといわれる

#1

投稿記事 by 五穀豊穣 » 11年前

まず、コードを。
初心者の汚いコードで、関係のないコメントもあってすいませんm(_ _)m

コード:

//graphic.h

#include "graphic.h"
#include "Dxlib.h"
#include "define.h"

Graphic graphic;

void makedummy(){
	dummygr = MakeGraph(2, 2);
}

void GrSet::update(){
	if (animate&&animeframe){//draw==0でも進行
		animecnt++;
		if (animecnt%animeframe==0){
			it++;
			if (it == img.end()){
				it = img.begin();
				if (!loop)draw = 0;
			}
		}
	}
}

int GrSet::getgr(){
	if (draw){
		return(*it);
	}
	else return(dummygr);
}

void Graphic::load(){
	static bool isloaded = 0;
	if (isloaded==1)return;
	isloaded = 1;

	makedummy();
	int handle[64];
	LoadDivGraph("img/gr.png", 64, 4, 16, 8, 8, handle, 1);
	player.getnormal().setgr(handle,1);
	player.getdead().setgr(handle + 1, 3);
	player.getdead().setloop(0);
	shot.getnormal().setgr(handle+4, 2);
	shot.getdead().setgr(handle + 6, 2);
	shot.getdead().setloop(0);
	{	GrSet enenormal;
		GrSet enedead;
		enedead.setloop(0);
		enemy.resize(ENETYPE);
		for (int i = 0; i < ENETYPE; i++){
			enenormal.setgr(handle + 8 + 4 * i, 2);
			enedead.setgr(handle + 8 + 4 * i + 2, 2);
			enemy[i].getnormal() = enenormal;
			enemy[i].getdead() = enedead;}
	}
	GrSet bulletnormal;
	GrSet bulletdead;
	bulletdead.setloop(0);
	bulletdead.setdraw(0);
	bullet.resize(ENETYPE);
	for (int i = 0; i < ENETYPE; i++){
		bulletnormal.setgr(handle + 32 + 2 * i, 2);
		bulletdead.setgr(handle+63, 1);//dummy
		bullet[i].getnormal() =bulletnormal;
		bullet[i].getdead() = bulletdead;
	}
}

//obj.h

#pragma once
#include "graphic.h"
#include <cmath>
#include "DxLib.h"

class GrSet;
class GrSetSet;
class Graphic;
struct Pos;
class Obj;


struct Pos{
	float x, y;
	Pos(){ x = 0, y = 0; }
	Pos(float X, float Y){ x = X; y = Y; }
	Pos operator+(const Pos& p){ Pos a(x + p.x, y + p.y); return a; }
	Pos operator-(const Pos& p){ Pos a(x - p.x, y - p.y); return a; }
	Pos operator*(const float& f){ Pos a(x*f, y*f); return a; }
	Pos operator/(const float& f){ Pos a(x/f, y/f); return a; }
	Pos & operator+=(const Pos& p){ x += p.x, y += p.y; return *this; }
	Pos & operator-=(const Pos& p){ x -= p.x, y -= p.y; return *this; }
	Pos & operator*=(const float& f){ x *= f, y *= f; return *this; }
	Pos & operator/=(const float& f){ x /= f, y /= f; return *this; }
	float norm(){ return(sqrt(x*x + y*y)); }
	float angle(){ return(atan2(y, x)); }
	Pos& normalize(){ if (abs(norm())<0.00001F)*this /= norm(); return *this; }
};

Pos makepos(float x, float y);

class Obj{
	bool flag;
	Pos pos,speed;
	GrSetSet gr;//←ここだけにエラー!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
public:

};

class Player:public Obj{
	void init();
	void update();
};
結果:エラー 1 error C2079: 'Obj::gr' が 未定義の class 'GrSetSet' で使用しています。

不思議なのは、問題の行GrSetSet gr;をコメントアウトすると正常にコンパイルされることです。(graphic.hのGraphicでもGrSetSetを使っているのに)
この症状は、循環参照が起きると起こる、と聞きましたが、見つかりません。

原因がわかる方、いらっしゃったらお願いします。

五穀豊穣

Re: [C++]別ファイルでクラスが未定義だといわれる

#2

投稿記事 by 五穀豊穣 » 11年前

連投すいません。
環境はWindows8,visualstudio2013express,dxライブラリ、ということを書き忘れました。

あと、ここの掲示板の[コード]の中身が正常に表示されてない(真ん中の行にだけたくさん改行なしにかいてあるように見える)んですが、ほかの方の質問もそう見えたのでこの症状は私だけですかね?

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: [C++]別ファイルでクラスが未定義だといわれる

#3

投稿記事 by みけCAT » 11年前

Graphicクラスの定義が見つからないのでそれが通るのかはわかりませんが、
クラスを前方宣言だけでいいのは、そのクラスのポインタや参照を使うときだけだという気がします。

ポインタ→どんな型のポインタでも、あるシステムでのポインタのサイズは一定(例:4バイト)
クラスそのもののデータ→もちろんその構造によってサイズが変わる
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: [C++]別ファイルでクラスが未定義だといわれる

#4

投稿記事 by みけCAT » 11年前

五穀豊穣 さんが書きました:あと、ここの掲示板の[コード]の中身が正常に表示されてない(真ん中の行にだけたくさん改行なしにかいてあるように見える)んですが、ほかの方の質問もそう見えたのでこの症状は私だけですかね?
おそらくIE10をお使いですね?
Firefoxなど、他のブラウザを使用するといいと思います。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
usao
記事: 1889
登録日時: 12年前
連絡を取る:

Re: [C++]別ファイルでクラスが未定義だといわれる

#5

投稿記事 by usao » 11年前

GrSetSetクラスの宣言が書かれたヘッダが別途あるのだと思いますが,
(例えばそれが GrSetSet.h とかいう名前だとして)
obj.h をincludeしている.cpp等で,そのヘッダGrSetSet.hをincludeしていますでしょうか?

五穀豊穣
記事: 10
登録日時: 11年前

Re: [C++]別ファイルでクラスが未定義だといわれる

#6

投稿記事 by 五穀豊穣 » 11年前

みけCAT さんが書きました:Graphicクラスの定義が見つからないのでそれが通るのかはわかりませんが、
クラスを前方宣言だけでいいのは、そのクラスのポインタや参照を使うときだけだという気がします。

ポインタ→どんな型のポインタでも、あるシステムでのポインタのサイズは一定(例:4バイト)
クラスそのもののデータ→もちろんその構造によってサイズが変わる
あれはエラーが起きてからこれで治らないかと適当にぶち込んだものでしたw

五穀豊穣
記事: 10
登録日時: 11年前

Re: [C++]別ファイルでクラスが未定義だといわれる

#7

投稿記事 by 五穀豊穣 » 11年前

usaoさんのご指摘で気づいたのですが、コードを張り付け間違えてました。。。わかりにくいことになってしまってすいません。。。
上で//graphic.hと書いてある部分は//graphic.cppです。

コード:

//本当のgraphic.h
#pragma once
#include<vector>
#include <string>
#include <map>
#include "define.h"

static int dummygr;
void makedummy();


class GrSet{//必要があれば回転とサイズを実装
	std::vector<int> img;
	std::vector<int>::iterator it = img.begin();
	int animeframe = 30;
	int animecnt=0;
	bool loop = 1;
	int animate = 1;
	bool draw = 1;
public:
	void operator=(const GrSet & a){ img = a.img; it = img.begin(); animeframe = a.animeframe;
	animecnt = a.animecnt; loop = a.loop; animate = a.animate; draw = a.draw;}

	void addgr(int g){ img.push_back(g); }
	void setgr(int* g, int num){
		img.clear();
		for (int i = 0; i < num; i++){
			addgr(g[i]);
		}
	}

	void update();
	int getgr();
	void animereset(){ it = img.begin(); animecnt = 0; }

	void setanimeframe(int f){ animeframe = f; }
	void setloop(bool l){ loop = l; }
	void setanimate(int a){ animate = a; }
	void setdraw(bool d){ draw = d; }

	bool getdraw(){ return draw; }
};

class GrSetSet{
	GrSet normal;
	GrSet dead;
	GrSet& currentset=normal;
public:
	void operator=(const GrSetSet &a){ normal = a.normal, dead = a.dead, currentset = normal; }

	GrSet & getnormal(){return normal; }
	GrSet & getdead(){ return dead; }

	void norm(){ normal.animereset(); currentset = dead; }
	void die(){ dead.animereset();currentset = dead; }

	void update(){ currentset.update(); }
	int getgr(){ return currentset.getgr(); }
	bool isgone(){ if (currentset.getdraw() == 0)return 1; else return 0; }
};

class Graphic{
	GrSetSet player;
	GrSetSet shot;
	std::vector<GrSetSet> enemy;
	std::vector<GrSetSet> bullet;
public:
	void load();

	const GrSetSet & getplayer() const{ return(player); }
	const GrSetSet & getshot() const{ return(shot); }
	const GrSetSet & getenemy(int id) const{ return(enemy[id]); }
	const GrSetSet & getbullet(int id) const{ return(bullet[id]); }
};

extern Graphic graphic;
こんな感じです。
あと、[コード]表示の件ですが、chromeにしたら治りました!

返信を下さった皆さんありがとうございます!半日でこんなにも返信をいただいて結構感動しておりますw

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: [C++]別ファイルでクラスが未定義だといわれる

#8

投稿記事 by みけCAT » 11年前

手元の環境(gcc 4.7.2)で実験したところ、コンパイルが通りました。

graphic.h

コード:

#pragma once
#include<vector>
#include <string>
#include <map>
//#include "define.h"
 
static int dummygr;
void makedummy();
 
 
class GrSet{//必要があれば回転とサイズを実装
    std::vector<int> img;
    std::vector<int>::iterator it = img.begin();
    int animeframe = 30;
    int animecnt=0;
    bool loop = 1;
    int animate = 1;
    bool draw = 1;
public:
    void operator=(const GrSet & a){ img = a.img; it = img.begin(); animeframe = a.animeframe;
    animecnt = a.animecnt; loop = a.loop; animate = a.animate; draw = a.draw;}
 
    void addgr(int g){ img.push_back(g); }
    void setgr(int* g, int num){
        img.clear();
        for (int i = 0; i < num; i++){
            addgr(g[i]);
        }
    }
 
    void update();
    int getgr();
    void animereset(){ it = img.begin(); animecnt = 0; }
 
    void setanimeframe(int f){ animeframe = f; }
    void setloop(bool l){ loop = l; }
    void setanimate(int a){ animate = a; }
    void setdraw(bool d){ draw = d; }
 
    bool getdraw(){ return draw; }
};
 
class GrSetSet{
    GrSet normal;
    GrSet dead;
    GrSet& currentset=normal;
public:
    void operator=(const GrSetSet &a){ normal = a.normal, dead = a.dead, currentset = normal; }
 
    GrSet & getnormal(){return normal; }
    GrSet & getdead(){ return dead; }
 
    void norm(){ normal.animereset(); currentset = dead; }
    void die(){ dead.animereset();currentset = dead; }
 
    void update(){ currentset.update(); }
    int getgr(){ return currentset.getgr(); }
    bool isgone(){ if (currentset.getdraw() == 0)return 1; else return 0; }
};
 
class Graphic{
    GrSetSet player;
    GrSetSet shot;
    std::vector<GrSetSet> enemy;
    std::vector<GrSetSet> bullet;
public:
    void load();
 
    const GrSetSet & getplayer() const{ return(player); }
    const GrSetSet & getshot() const{ return(shot); }
    const GrSetSet & getenemy(int id) const{ return(enemy[id]); }
    const GrSetSet & getbullet(int id) const{ return(bullet[id]); }
};
 
extern Graphic graphic;
obj.h

コード:

#pragma once
#include "graphic.h"
#include <cmath>
//#include "DxLib.h"

using namespace std;

class GrSet;
class GrSetSet;
class Graphic;
struct Pos;
class Obj;
 
 
struct Pos{
    float x, y;
    Pos(){ x = 0, y = 0; }
    Pos(float X, float Y){ x = X; y = Y; }
    Pos operator+(const Pos& p){ Pos a(x + p.x, y + p.y); return a; }
    Pos operator-(const Pos& p){ Pos a(x - p.x, y - p.y); return a; }
    Pos operator*(const float& f){ Pos a(x*f, y*f); return a; }
    Pos operator/(const float& f){ Pos a(x/f, y/f); return a; }
    Pos & operator+=(const Pos& p){ x += p.x, y += p.y; return *this; }
    Pos & operator-=(const Pos& p){ x -= p.x, y -= p.y; return *this; }
    Pos & operator*=(const float& f){ x *= f, y *= f; return *this; }
    Pos & operator/=(const float& f){ x /= f, y /= f; return *this; }
    float norm(){ return(sqrt(x*x + y*y)); }
    float angle(){ return(atan2(y, x)); }
    Pos& normalize(){ if (abs(norm())<0.00001F)*this /= norm(); return *this; }
};
 
Pos makepos(float x, float y);
 
class Obj{
    bool flag;
    Pos pos,speed;
    GrSetSet gr;//←ここだけにエラー!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
public:
 
};
 
class Player:public Obj{
    void init();
    void update();
};
hoge.cpp

コード:

#include "obj.h"

int main(void){return 0;}
コンパイルのコマンド

コード:

g++ hoge.cpp -std=c++11
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

五穀豊穣
記事: 10
登録日時: 11年前

Re: [C++]別ファイルでクラスが未定義だといわれる

#9

投稿記事 by 五穀豊穣 » 11年前

わざわざありがとうございます!

同じようにやってみたところ、こちらでも例のエラーは消えました。
その後、コメントアウトする位置を変えていろいろやったところ、
define.h

コード:

#pragma once
//#include "obj.h" ←ここを消しただけで、あのエラーが出なくなる 

static const int ENETYPE = 6;
ということがわかりました。
実際私も何を考えてincludeしたのかはわかりませんw

これでとりあえずは解決したのですが、このエラーの理由はいったい何なんでしょうか…?

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: [C++]別ファイルでクラスが未定義だといわれる

#10

投稿記事 by みけCAT » 11年前

define.h内でincludeしているobj.hで、GrSetSetの定義より前にObjクラスの定義が来るからだと思います。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

五穀豊穣
記事: 10
登録日時: 11年前

Re: [C++]別ファイルでクラスが未定義だといわれる

#11

投稿記事 by 五穀豊穣 » 11年前

またもや連投すいません

main内で、obj.hとgraphic.hの内容を使ってみても、エラーは出ませんでした。
やはり循環参照をいうやつなんでしょうか?#pragma once していれば大丈夫だとおもっていたんですが…
各ファイルの#include 部分を書いておきます。

//ヘッダ=================================================================================
obj.h

コード:

#pragma once
#include "graphic.h"
#include <cmath>
#include "DxLib.h"
graphic.h

コード:

#pragma once
#include<vector>
#include <string>
#include <map>
#include "define.h"
key.h

コード:

#pragma once
#include "DxLib.h"
#include "obj.h"
define.h

コード:

#pragma once
//#include "obj.h"  //ここを書くとエラー!!!!!!!!!!!!!!!!!!!
//C++===================================================================================================

graphic.cpp

コード:

#include "graphic.h"
#include "Dxlib.h"
#include "define.h"


main.cpp

コード:

#include "DxLib.h"
#include "graphic.h"
#include "obj.h"
obj.cpp

コード:

#include "obj.h"

五穀豊穣
記事: 10
登録日時: 11年前

Re: [C++]別ファイルでクラスが未定義だといわれる

#12

投稿記事 by 五穀豊穣 » 11年前

みけCAT さんが書きました:define.h内でincludeしているobj.hで、GrSetSetの定義より前にObjクラスの定義が来るからだと思います。
なるほど!そんなことがあるんですか
しかしdefine.hでobj.hをincludeしたとき、obj.hの先頭の#include"graphic.h"は読まれないんですか?

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: [C++]別ファイルでクラスが未定義だといわれる

#13

投稿記事 by みけCAT » 11年前

五穀豊穣 さんが書きました:
みけCAT さんが書きました:define.h内でincludeしているobj.hで、GrSetSetの定義より前にObjクラスの定義が来るからだと思います。
なるほど!そんなことがあるんですか
しかしdefine.hでobj.hをincludeしたとき、obj.hの先頭の#include"graphic.h"は読まれないんですか?
define.hはgraphic.hからincludeされているため、#pragma onceの効果で読まれないと思います。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

五穀豊穣
記事: 10
登録日時: 11年前

Re: [C++]別ファイルでクラスが未定義だといわれる

#14

投稿記事 by 五穀豊穣 » 11年前

define.hはgraphic.hからincludeされているため、#pragma onceの効果で読まれないと思います。[/quote]

なるほど、つまり、#pragma once のせいで読み込まれる順番が違ってしまった,という感じですね。
大体わかりました、ありがとうございます!

こんなに親切な回答をありがとうございました、とても助かりましたm(_ _)m
自分もc++がわかるようになってきたらいつかこの掲示板に恩返しをしたいと思いますw
では、解決チェックをつけておきます。

閉鎖

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