undefined reference to Base::object linker error @ c++ w/ freeglut [duplicate]
Asked Answered
E

2

4

I have this code

/////////////////////////////////////Gnome.cpp file

 #include "Living.h"

class Gnome:public Living{
private:

public:
Gnome();
void drawObjects();
};


Gnome::Gnome()
{
spriteImg = new Sprite("graphics/gnome.bmp"); //<-------------this is where it says there is the error

loaded = true;
}

///////////////////////////////////Living.h file

#include <iostream>

 #include "Sprite.h"


using namespace std;

class Sprite;

class Living{

protected:
int x,y;
static Sprite *spriteImg; //= NULL;
bool loaded;


void reset();


public:

Living();
~Living();
int getX();
void setX(int _x);
int getY();
void setY(int _y);
void virtual drawObjects() =0;


};

// living.cpp

#include "Living.h"


Living::Living()
{
x=y=0;
reset();
}


Living::~Living()
{
delete spriteImg;

}

void Living::setX(int _x)
{
x=_x;
}

int Living::getX()
{
return x;
}


void Living::setY(int _y)
{
y=_y;
}

int Living::getY()
{
return y;
}


void Living::reset()
{
spriteImg = NULL;
loaded = false;
}

// sprite.h

#include <GL/glut.h>

 #include <string>

using namespace std;

class ImageLoader;

class Sprite
{
public:
/**
* Enable 2D drawing mode to draw our sprites. This function MUST be called before
* any sprite is drawn on screen using the draw method.
*/
static void enable2D();

/**
* Disables the 2D drawing. This can be called before you are done drawing all 2D
* sprites and want to draw 3D now.
*/
static void disable2D();

Sprite(string filename);
virtual ~Sprite();

virtual void draw();
virtual void drawLiving(int dir, int flag); //flag=1 move
virtual void draw(int X, int Y);
virtual void rotate(GLint degrees);

// getter and setter methods
GLint getAngle() const;
void setAngle(GLint degrees);
void setX(GLdouble x);
void setY(GLdouble y);
GLint getHeight() const;
GLint getWidth() const;

/**
* Sets the pivot point in relation to the sprite itself, that is using the object
* coordiantes system. In this coordiantes system the bottom left point of the object
* is at (0, 0) and the top right is at (1, 1).
*
* E.g. to set the pivot to be in the middle of the sprite use (0.5, 0.5)
* Default values are (1, 1).
* @param pivotX Can be any value, but when x is in the range [0, 1] the pivot is inside the
* sprite where 0 is the left edge of the sprite and 1 is the right edge of the sprite.
* @param pivotY Can be any value, but when y is in the range [0, 1] the pivot is inside the
* sprite where 0 is the bottom edge of the sprite and 1 is the top edge of the sprite.
*/
void setPivot(GLfloat pivotX, GLfloat pivotY);
GLfloat getPivotX() const;
GLfloat getPivotY() const;

GLdouble getX() const;
GLdouble getY() const;

/**
* Sets the pivot to be at the point where object's pivot is set.
* @param obj The reference object to whose pivot we will set this pivot to be.
* Note: if the obj pivot changes or the obj moves after the setPivot call has
* been issued, the pivot of this object will not reflect this changes. You must
* call setPivot again with that object to update the pivot information.
*/
void setPivot(const Sprite &obj);

/**
* Sets the scale of the object. A scale of (1.0, 1.0) means the sprite
* maintains its original size. Values larger than 1 scale the sprite up
* while values less than 1 shrink it down.
*/
void setScale(GLfloat x, GLfloat y);
private:
ImageLoader *image;
GLuint textureID;
GLint angle;
GLdouble x;
GLdouble y;
GLfloat pivotX;
GLfloat pivotY;
GLfloat scaleX;
GLfloat scaleY;
GLint step;
//GLint dir;

//-----------------------------------------------------------------------------
// Initializes extensions, textures, render states, etc. before rendering
//-----------------------------------------------------------------------------
void initScene();

/**
* A helper function taken from http://www.opengl.org/resources/features/OGLextensions/
* to help determine if an OpenGL extension is supported on the target machine at run-time
* @param extension The extension name as a string.
* @return True if extension is supported and false if it is not.
*/
bool isExtensionSupported(const char *extension) const;
};

// if you need the implementation plz let me know

//and finally the engine class

 #include <conio.h>

 #include "Living.h"

 #include "Gnome.h"



using namespace std;
class Engine{


private:
vector<char*> gamemap;
int score;
vector <Living*> gameobjs;
void FindRandomPos(int &x_pos,int &y_pos);
int mapMaxX;
int mapMaxY;


void collisionDetecion(int pX,int pY);



public:


Engine();
void init(const char* mapname="defaultmap.txt",int gnomes=1,int traals=1,int diamonds=10);
void printMap();
void printMap2();
void movePotter();
void calculateScroll();
int getScore();
int getMapMaxX ();
int getMapMaxY ();


};

//and the partial engine.cpp

void Engine::init(const char* mapname,int gnomes,int traals,int diamonds)
{
int i=0;
// int z=0;
mapMaxX=0;
mapMaxY=0;





int x_pos,y_pos;

int countobjs=0;


//gnomes
for(int i=0;i<gnomes;i++)
{
FindRandomPos(x_pos,y_pos);
gameobjs.push_back( new Gnome ); //<---------------here is where the error should begin i think
gameobjs[countobjs]->setX(x_pos);
gameobjs[countobjs]->setY(y_pos);
gamemap[gameobjs[countobjs]->getX()][gameobjs[countobjs]->getY()]='3';
countobjs++;
 }
}

so when I try to build it, the linker shows this error: Undefined reference to Living::spriteImg

Enkindle answered 31/1, 2012 at 3:43 Comment(0)
S
12

It is a Linker error, which tells you that the Linker cannot find definition for the static member Living::spriteImg, this is because you just declare it in your class but you never defined it.

You ned to define the static member in your Living.cpp:

Sprite* Living::spriteImg = NULL;

Remember that you need to define it in one and only one .cpp file.

Good Read:
What is the difference between a definition and a declaration?

Schwerin answered 31/1, 2012 at 3:46 Comment(0)
G
0

Living::SpriteImg is a static data member. You have only declared it in the class Living.

However, static data members also needs to be defined separately, preferably in a .cpp file.

// .cpp file
Sprite* Living::spriteImg = 0;
Goshawk answered 31/1, 2012 at 3:47 Comment(3)
preferably in a .cpp, No It must be in a cpp.Schwerin
@Als, wrong. If the given .h file is included only in 1 translation unit, then you can very well define a static member inside the same .h file. Another scenario: for templates, the static member definition has to be visible to all translation units, so in that case the definition is mostly included in the .h file! That's why I used preferably.Goshawk
In OP's scenario theres no preferably its only must. OP is not using templates neither is the .h file being included in just one translation unit(It is rare almost unlikely that an .h file will be inlcuded in only TU in a project)Schwerin

© 2022 - 2024 — McMap. All rights reserved.