ページ 1 / 1
[C++]別ファイルでクラスが未定義だといわれる
Posted: 2013年11月26日(火) 01:05
by 五穀豊穣
まず、コードを。
初心者の汚いコードで、関係のないコメントもあってすいません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++]別ファイルでクラスが未定義だといわれる
Posted: 2013年11月26日(火) 01:12
by 五穀豊穣
連投すいません。
環境はWindows8,visualstudio2013express,dxライブラリ、ということを書き忘れました。
あと、ここの掲示板の[コード]の中身が正常に表示されてない(真ん中の行にだけたくさん改行なしにかいてあるように見える)んですが、ほかの方の質問もそう見えたのでこの症状は私だけですかね?
Re: [C++]別ファイルでクラスが未定義だといわれる
Posted: 2013年11月26日(火) 07:49
by みけCAT
Graphicクラスの定義が見つからないのでそれが通るのかはわかりませんが、
クラスを前方宣言だけでいいのは、そのクラスのポインタや参照を使うときだけだという気がします。
ポインタ→どんな型のポインタでも、あるシステムでのポインタのサイズは一定(例:4バイト)
クラスそのもののデータ→もちろんその構造によってサイズが変わる
Re: [C++]別ファイルでクラスが未定義だといわれる
Posted: 2013年11月26日(火) 08:46
by みけCAT
五穀豊穣 さんが書きました:あと、ここの掲示板の[コード]の中身が正常に表示されてない(真ん中の行にだけたくさん改行なしにかいてあるように見える)んですが、ほかの方の質問もそう見えたのでこの症状は私だけですかね?
おそらくIE10をお使いですね?
Firefoxなど、他のブラウザを使用するといいと思います。
Re: [C++]別ファイルでクラスが未定義だといわれる
Posted: 2013年11月26日(火) 09:08
by usao
GrSetSetクラスの宣言が書かれたヘッダが別途あるのだと思いますが,
(例えばそれが GrSetSet.h とかいう名前だとして)
obj.h をincludeしている.cpp等で,そのヘッダGrSetSet.hをincludeしていますでしょうか?
Re: [C++]別ファイルでクラスが未定義だといわれる
Posted: 2013年11月26日(火) 16:40
by 五穀豊穣
みけCAT さんが書きました:Graphicクラスの定義が見つからないのでそれが通るのかはわかりませんが、
クラスを前方宣言だけでいいのは、そのクラスのポインタや参照を使うときだけだという気がします。
ポインタ→どんな型のポインタでも、あるシステムでのポインタのサイズは一定(例:4バイト)
クラスそのもののデータ→もちろんその構造によってサイズが変わる
あれはエラーが起きてからこれで治らないかと適当にぶち込んだものでしたw
Re: [C++]別ファイルでクラスが未定義だといわれる
Posted: 2013年11月26日(火) 16:48
by 五穀豊穣
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
Re: [C++]別ファイルでクラスが未定義だといわれる
Posted: 2013年11月26日(火) 22:02
by みけCAT
手元の環境(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
Re: [C++]別ファイルでクラスが未定義だといわれる
Posted: 2013年11月26日(火) 23:07
by 五穀豊穣
わざわざありがとうございます!
同じようにやってみたところ、こちらでも例のエラーは消えました。
その後、コメントアウトする位置を変えていろいろやったところ、
define.h
コード:
#pragma once
//#include "obj.h" ←ここを消しただけで、あのエラーが出なくなる
static const int ENETYPE = 6;
ということがわかりました。
実際私も何を考えてincludeしたのかはわかりませんw
これでとりあえずは解決したのですが、このエラーの理由はいったい何なんでしょうか…?
Re: [C++]別ファイルでクラスが未定義だといわれる
Posted: 2013年11月26日(火) 23:19
by みけCAT
define.h内でincludeしているobj.hで、GrSetSetの定義より前にObjクラスの定義が来るからだと思います。
Re: [C++]別ファイルでクラスが未定義だといわれる
Posted: 2013年11月26日(火) 23:25
by 五穀豊穣
またもや連投すいません
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
Re: [C++]別ファイルでクラスが未定義だといわれる
Posted: 2013年11月26日(火) 23:28
by 五穀豊穣
みけCAT さんが書きました:define.h内でincludeしているobj.hで、GrSetSetの定義より前にObjクラスの定義が来るからだと思います。
なるほど!そんなことがあるんですか
しかしdefine.hでobj.hをincludeしたとき、obj.hの先頭の#include"graphic.h"は読まれないんですか?
Re: [C++]別ファイルでクラスが未定義だといわれる
Posted: 2013年11月26日(火) 23:31
by みけCAT
五穀豊穣 さんが書きました:みけ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の効果で読まれないと思います。
Re: [C++]別ファイルでクラスが未定義だといわれる
Posted: 2013年11月26日(火) 23:54
by 五穀豊穣
define.hはgraphic.hからincludeされているため、#pragma onceの効果で読まれないと思います。[/quote]
なるほど、つまり、#pragma once のせいで読み込まれる順番が違ってしまった,という感じですね。
大体わかりました、ありがとうございます!
こんなに親切な回答をありがとうございました、とても助かりましたm(_ _)m
自分もc++がわかるようになってきたらいつかこの掲示板に恩返しをしたいと思いますw
では、解決チェックをつけておきます。