Trouble with multiple classes and header files
Author |
Message |
HyperFlexed
|
Posted: Sun Jun 20, 2010 3:09 pm Post subject: Trouble with multiple classes and header files |
|
|
disclaimer: very new with C++. A lot of it still warps my mind. Anywho, I have 2 classes I'm working on for a game, Entity (base class for all the objects in the game), and SpriteSheet (a simple representation of all the sprites for my game).
Entity.h
c++: | #include "SpriteSheet.h"
class Entity {
private:
int x, y, xSpd, ySpd, xAcc, yAcc;
SpriteSheet sprites;
public:
// Constructor
Entity(int x = 0, int y = 0, int xSpd = 0, int ySpd = 0, int xAcc = 0, int yAcc = 0, SpriteSheet sprites);
// Destructor
~Entity ();
// Set co-ordinates on screen
void setX(int x);
void setY(int y);
// Set speed
void setXSpd(int xSpd);
void setYSpd(int ySpd);
// Set acceleration
void setXAcc(int xAcc);
void setYAcc(int yAcc);
// Get x and y co-ordinates
int getX();
int getY();
// Get x and y speed
int getXSpd();
int getYSpd();
// Get x and y acceleration
int getXAcc();
int getYAcc();
}; |
Entity.cpp
c++: | #include "SpriteSheet.h"
class Entity {
private:
int x, y, xSpd, ySpd, xAcc, yAcc;
SpriteSheet sprites;
public:
// Constructor
Entity(int x, int y, int xSpd, int ySpd, int xAcc, int yAcc, SpriteSheet sprites){
this->x = x;
this->y = y;
this->xSpd = xSpd;
this->ySpd = ySpd;
this->xAcc = xAcc;
this->yAcc = yAcc;
this->sprites = sprites;
}
// Destructor
~Entity (){
delete &x;
delete &y;
delete &xSpd;
delete &ySpd;
delete &xAcc;
delete &yAcc;
delete &sprites;
}
// Set co-ordinates on screen
void setX(int x){this->x = x;}
void setY(int y){this->y = y;}
// Set speed
void setXSpd(int xAcc){this->xSpd = xAcc;}
void setYSpd(int yAcc){this->ySpd = yAcc;}
// Set acceleration
void setXAcc(int xAcc){this->xAcc = xAcc;}
void setYAcc(int yAcc){this->yAcc = yAcc;}
// Get x and y co-ordinates
int getX(){return x;}
int getY(){return y;}
// Get x and y speed
int getXSpd(){return xSpd;}
int getYSpd(){return ySpd;}
// Get x and y acceleration
int getXAcc(){return xAcc;}
int getYAcc(){return yAcc;}
}; |
SpriteSheet.h
c++: | #include "SDL/SDL.h"
#include "SDL/SDL_image.h"
class SpriteSheet{
private:
SDL_Surface *spritesheet;
SDL_Rect *clipArray;
public:
SpriteSheet(int numStates, int numAnimationStates, SDL_Surface *spritesheet, SDL_Rect *clipArray);
}; |
SpriteSheet.cpp
c++: | #include "SDL/SDL.h"
#include "SDL/SDL_image.h"
class SpriteSheet{
private:
SDL_Surface *spritesheet;
SDL_Rect *clipArray;
public:
SpriteSheet(int numStates, int numAnimationStates, SDL_Surface *spritesheet, SDL_Rect *clipArray){
// do stuff
}
}; |
SpriteSheet is a bit sparse at the moment. I'll fill it in later. The issue is that when I try to compile Entity.cpp I get the following error:
code: | johnny@picard:~/coding/shmupGame$ g++ Entity.cpp
Entity.cpp: In constructor ?Entity::Entity(int, int, int, int, int, int, SpriteSheet)?:
Entity.cpp:10: error: no matching function for call to ?SpriteSheet::SpriteSheet()?
SpriteSheet.h:10: note: candidates are: SpriteSheet::SpriteSheet(int, int, SDL_Surface*, SDL_Rect*)
SpriteSheet.h:4: note: SpriteSheet::SpriteSheet(const SpriteSheet&) |
As far as I can tell the SpriteSheet class has its constructor there plain as day. Any idea why my program is choking? |
|
|
|
|
|
Sponsor Sponsor
|
|
|
TerranceN
|
Posted: Sun Jun 20, 2010 3:35 pm Post subject: Re: Trouble with multiple classes and header files |
|
|
You are implementing the class methods wrong.
For example lets say I have a class that has a number, a constructor, a getter and setter:
SomeClass.h
c++: | class SomeClass
{
int number;
public:
SomeClass(int newNumber);
int GetNumber();
void SetNumber(int newNumber);
}; |
SomeClass.cpp
c++: | #include "SomeClass.h"
SomeClass::SomeClass(int newNumber)
{
number = newNumber;
}
int SomeClass::GetNumber()
{
return number;
}
void SomeClass::SetNumber(int newNumber)
{
number = newNumber;
} |
You can also implement the functions when you declare them in your header file (exactly like you have in your .cpp files right now)
Hope that helps. |
|
|
|
|
|
HyperFlexed
|
Posted: Sun Jun 20, 2010 4:14 pm Post subject: Re: Trouble with multiple classes and header files |
|
|
so what you're saying is in a header file you use the class construct, but in the actual cpp file you use the :: operator instead? Any reason for why its done this way?
Also, I notice that your member variable doesn't get declared in the .cpp file. The header takes care of this?
I fixed up my files as you had shown, and added some include guards (to mitigate the remaining errors). Works like a charm now. Are header guards the only viable way of preventing redefinition errors? I don't recall seeing so many of them in other programs. |
|
|
|
|
|
HyperFlexed
|
Posted: Sun Jun 20, 2010 4:49 pm Post subject: Re: Trouble with multiple classes and header files |
|
|
Hmm, new one now.
I've created a main.cpp so I can test my objects
c++: | #include "Entity.h"
#include "SpriteSheet.h"
int main(int argc, char **argv){
Entity *ship = new Entity(10,10,10,10,10,10,NULL);
SpriteSheet *sheet = new SpriteSheet(10,10,NULL,NULL);
return 0;
} |
I try compiling:
code: | johnny@picard:~/coding/shmupGame$ g++ main.cpp -lSDL -lSDL_image
In file included from main.cpp:2:
SpriteSheet.h:7: error: redefinition of ?class SpriteSheet?
SpriteSheet.h:7: error: previous definition of ?class SpriteSheet? |
So I look at SpriteSheet.h:
c++: | #ifndef SDL_HEADERS
#define SDL_HEADERS
#include "SDL/SDL.h"
#include "SDL/SDL_image.h"
#endif
class SpriteSheet{
private:
SDL_Surface *spritesheet;
SDL_Rect *clipArray;
public:
SpriteSheet(int numStates, int numAnimationStates, SDL_Surface *spritesheet, SDL_Rect *clipArray);
}; |
and I can't see a redefinition. However, I see that in main, Entity.h is included first, so maybe it's a problem with that file:
c++: | #ifndef SPRITESHEET_H
#define SPRITESHEET_H
#include "SpriteSheet.h"
#endif
class Entity {
private:
int x, y, xSpd, ySpd, xAcc, yAcc;
SpriteSheet *sprites;
public:
// Constructor
Entity(int x = 0, int y = 0, int xSpd = 0, int ySpd = 0, int xAcc = 0, int yAcc = 0, SpriteSheet *sprites = NULL);
// Destructor
~Entity ();
// Set co-ordinates on screen
void setX(int x);
void setY(int y);
// Set speed
void setXSpd(int xSpd);
void setYSpd(int ySpd);
// Set acceleration
void setXAcc(int xAcc);
void setYAcc(int yAcc);
// Get x and y co-ordinates
int getX();
int getY();
// Get x and y speed
int getXSpd();
int getYSpd();
// Get x and y acceleration
int getXAcc();
int getYAcc();
}; |
But it has an include guard, so I don't see how I'm getting a redefinition error.
Edit: I see now that since Entity.h includes SpriteSheet.h, I need an include guard in main.cpp (or I have to simply remove SpriteSheet's include). Now that I've done that, I get:
code: | johnny@picard:~/coding/shmupGame$ g++ main.cpp -lSDL -lSDL_image
/tmp/ccBRFi8P.o: In function `main':
main.cpp:(.text+0x53): undefined reference to `Entity::Entity(int, int, int, int, int, int, SpriteSheet*)'
main.cpp:(.text+0x84): undefined reference to `SpriteSheet::SpriteSheet(int, int, SDL_Surface*, SDL_Rect*)'
collect2: ld returned 1 exit status |
and it looks like one of the most brutal errors I've ever seen. Strange references to tmp files. Random patches of hex digits. What's going on here? |
|
|
|
|
|
TerranceN
|
Posted: Sun Jun 20, 2010 5:12 pm Post subject: RE:Trouble with multiple classes and header files |
|
|
Why you use the :: operator
Separating the definition and implementation of a class is just like using function prototypes. But because the function is in a class you need to say what class its in (cause multiple classes could have a method with the same name). You do this using the scope resolution operator, ::
variables in classes
Yes the header takes care of it (unless its static, I dont remember why) because you are just defining the variable, not implementing it (giving it a value)
header guards
Yes, header guards are the accepted way of preventing redefinitions, but your header guards are wrong.
The way it works is by checking if a macro is defined using #ifndef. If not then you know that source has not been compiled, so you define the macro with #define and place your source code after it. This way if anything else #include's your code it wont be recompiled. The problem you have is that your source code is outside that if statement so the if statement does nothing
The header guard should look like this:
c++: | #ifndef MACRONAME
#define MACRONAME
// your code here
#endif
|
|
|
|
|
|
|
HyperFlexed
|
Posted: Sun Jun 20, 2010 5:22 pm Post subject: Re: RE:Trouble with multiple classes and header files |
|
|
TerranceN @ Sun Jun 20, 2010 5:12 pm wrote:
header guards
Yes, header guards are the accepted way of preventing redefinitions, but your header guards are wrong.
The way it works is by checking if a macro is defined using #ifndef. If not then you know that source has not been compiled, so you define the macro with #define and place your source code after it. This way if anything else #include's your code it wont be recompiled. The problem you have is that your source code is outside that if statement so the if statement does nothing
The header guard should look like this:
c++: | #ifndef MACRONAME
#define MACRONAME
// your code here
#endif
|
I'm using ifndef to make sure headers aren't included multiple times. The error I have now though is:
code: | main.cpp:(.text+0x53): undefined reference to `Entity::Entity(int, int, int, int, int, int, SpriteSheet*)'
main.cpp:(.text+0x84): undefined reference to `SpriteSheet::SpriteSheet(int, int, SDL_Surface*, SDL_Rect*)' |
I'm used to seeing this error when a function isn't defined, but I'm unsure as to how these functions haven't been defined. Is there any way I can see what g++ is looking at after all the preprocessor directives have been parsed? If I could do this, I would expect to see that main.cpp is missing definitions for the Entity and SpriteSheet constructors (based on the error above).
Also, what is the meaning of "main.cpp:(.text+0x84)"?
EDIT: I found the -E option (which outputs the preprocessed source). The result is here: http://pastebin.com/LQFFUAyq
The relevant code begins at line 4829
I can see that prototypes for my functions are there, but the full definitions are not. Do I have to somehow include Entity.cpp and SpriteSheet.cpp, or is this some kind of compiler flag? |
|
|
|
|
|
HyperFlexed
|
Posted: Sun Jun 20, 2010 5:38 pm Post subject: Re: Trouble with multiple classes and header files |
|
|
K, I feel dumb.
Tried:
code: | g++ Entity.cpp SpriteSheet.cpp main.cpp -o main |
And there was much rejoicing. Bits for your tolerance of my utter noobosity. |
|
|
|
|
|
|
|