C++ Class Linker error

Started by
13 comments, last by MJP 16 years ago
Hello, I'll spare you the details around this as they would take alot of reading and aren't really all that important, and jump right into the problem. I've just now added a class into a half-made game I'm working on, the class is something like this:
Quote:class Block { public: double destx; double desty; int destw; int desth; int setblock; int pos; bool move; //Function call to draw a sprite. void drawSprite(SDL_Surface *string, SDL_Surface *screen, int srcx, int srcy, int srcw, int srch, double destx, double desty, int destw, int desth); };
The function call is called like this:
Quote: drawSprite(sprite, screen, 52, 74, 52, 63, destx, desty, 52, 63);
And the forward declaraction in the class leads here:
Quote: #include "stdafx.h" #include <iostream> #include <string> #include "SDL/SDL.h" #include "SDL/SDL_image.h" void drawSprite(SDL_Surface *string, SDL_Surface *screen, int srcx, int srcy, int srcw, int srch, double destx, double desty, int destw, int desth) { SDL_Rect source; source.x = srcx; source.y = srcy; source.w = srcw; source.h = srch; SDL_Rect destination; destination.x = destx; destination.y = desty; destination.w = destw; destination.h = desth; SDL_BlitSurface(string, &source, screen, &destination); }
I think that's all the important parts... Now for the problem, when I compile I get the following error from the linker:
Quote: 1>Main.obj : error LNK2019: unresolved external symbol "public: void __thiscall Block::drawSprite(struct SDL_Surface *,struct SDL_Surface *,int,int,int,int,double,double,int,int)" (?drawSprite@Block@@QAEXPAUSDL_Surface@@0HHHHNNHH@Z) referenced in function _SDL_main 1>D:\Mor's C++\SDL launcher\Debug\SDL launcher.exe : fatal error LNK1120: 1 unresolved externals
So... yea, I've looked all over but can't find a good solution... so can anyone help me solve this, and possibly also explain for future reference?
Advertisement
Is drawSprite() a member function of Block? Because it is declared as such, but not defined as such (i.e., not Block::drawSprite()).

EDIT: You edited your post while I was typing. Now I'm pretty sure it's what I said above - you're declaring drawSprite() as a member function but defining it as a global free function. The definition should be:

void Block::drawSprite(...) { ... }
In the function implementation:
void drawSprite(SDL_Surface *string, SDL_Surface *screen,int srcx, int srcy, int srcw, int srch,double destx, double desty, int destw, int desth)


should infact be

void Block::drawSprite(SDL_Surface *string, SDL_Surface *screen,int srcx, int srcy, int srcw, int srch,double destx, double desty, int destw, int desth)


EDIT: Too slow =)
Best regards, Omid
Quote:
I'll spare you the details around this as they would take alot of reading and aren't really all that important, and jump right into the problem.

For future reference, it's worth noting that you can rarely make this judgment correctly -- that a particular piece of code isn't worth showing because it's 'not relevant' to the problem -- unless you know what the source of the problem is. And, almost by definition, if you know what the problem is, you don't generally need to ask for help.

Posting more of what you deemed unnecessary would have allowed for people to respond with a more definitive answer they could be more sure of, rather than initially just speculating until you happened along to edit and provide enough extra information.

It's much easier for us to wade through extra information than it is to work with too little information. A good guideline is that you should post exactly as much code as it takes to reproduce the bug, if at all possible -- this usually ensures we have enough context without you having to post you're entire multifile project, or whatever.
class Block{public:	double destx;	double desty;	int destw;	int desth;	int setblock;	int pos;	bool move;		//Function call to draw a sprite.		void drawSprite(SDL_Surface *string, SDL_Surface *screen, 				int srcx, int srcy, int srcw, int srch, 				double destx, double desty, int destw, int desth);};


I think you're misunderstanding a few things here.

First off, SDL draws to screen positions. Screen positions are integer, since they're a count of pixels. Why would you pass floating-point values (double) in?

Second, the point of member functions (i.e. the ones declared within a class body) is that they operate on an instance of the class. As you are hopefully aware, 'Block' is not simply storage for a few bits of data, but actually defines a data type. You can create variables of type Block as freely as you create variables of type int. That said, when you call drawSprite(), it will have to be called on a particular one of those variables; and that variable has data built into it - a 'destx', 'desty', 'destw', and 'desth'.

Consequently, it doesn't make any sense to pass those values into the function: you already have them - they are part of the object you are calling the function on.

Third, the block's "sprite" data is the source of the drawing. The screen should be the destination, because you are going to draw a Block onto the screen, and not the other way around. Thus, your member data should represent source x/y/w/h.

Fourth, it doesn't make any sense to expect the calling code (i.e. whereever it is that you create the Block and then .drawSprite() it) to know how big the block is. Knowing how big the block is, is the Block's responsibility. When you do the draw, the source and destination sizes ought to be the same. The caller should only have to specify where to draw the Block, and the Block takes care of the rest - by filling in its 'width' and 'height' for both source and destination width/height, where you create the SDL_Rects.

Although actually, depending on your situation, further reorganization might be necessary. What kinds of blocks do you have? Do they vary in size? In appearance?
@jpetrie, well, currently, I have nearly 1500 lines of code, I find it highly unappropriate to post it all here having you go through it all to look for the error, and like you said, I could reproduce the problem, but I already knew exactly what was the source of it, yet not the answer, hence why I only posted this. But thanks, I'll do that next time.(Btw, I just editted for noticing I wrote in the wrong error, not adding info to the problem =P)

@Zahlman, Oh, wow, that's... alot of errors you've found there >< let's see to them then...
First, I've set destx and desty to doubles because I don't move them by whole numbers, I needed the speed and distance to be exact, and therefore made them move in greater accuracy.
second, yea, I've realized that, but when I did it was already a little too late, like I said above, I have around 1500 lines of code as of now, and I really don't feel like going through all of them and fixing it, it's not really effecting the usage of the code, so I guess there's no use in doing that now either.
third, maybe this isn't so obvious from the function, the source here references to the spritesheet(Hence the source for the sprite), and draws it into it's destination(The screen), where it will be shown, that's what I meant by it.
fourth, that does make sense, but I'm using tetris blocks for this, that are obviously varying in size and appearance, furthermore, the source for all of the sprites is on one spritesheet, so I do need these extra source coordinates, and obviously, move them around after being printed to the screen, hence why destx and desty are needed, the destw and desth, however, like I said before, aren't, also, I need quite alot of these blocks, so having them all with a set source position isn't the smartest thing to do, as I'll then need to make a few classes instead of a few variables.
Thanks for trying to help though.

Thanks Gage and Omid, that seemed to fix it, but now I get a new problem, it says:
Quote:d:\mor's c++\sdl launcher\sdl launcher\main.cpp(63) : error C2761: 'void Block::drawSprite(SDL_Surface *,SDL_Surface *,int,int,int,int,double,double,int,int)' : member function redeclaration not allowed

And it points me to the line with destx, desty, destw and desth in the definition(void::drawSprite()).
Yet, how in that position, am I redeclaring the members? Aren't I'm just forward declaring them?
Post the new function definition. Also, are you sure you haven't made any other changes to the function definition other than adding the Block::?
Quote:
void Block::drawSprite(SDL_Surface *string, SDL_Surface *screen,
int srcx, int srcy, int srcw, int srch,
double destx, double desty, int destw, int desth);

And yes, yes I am, in fact, I haven't modified the code AT ALL since I posted this thread =\
Your declaration, which goes inside the curly braces after "Class Block", doesn't need the "Block::" scope added to it. You only need this for method definitions (where you implement the code) that are outside of the class definition (the curly braces).

Also you can use the "source" or "code" tags for posting code, rather than the "quote" tags. See the forum FAQ.
Yea, I realized that, I've only marked the declration outside of the class's definition and it gave me this error.
And thanks, I tried before, but it didn't seem to work, I'll try <!--STARTSCRIPT--><!--source lang="cpp"--><div class="source"><pre>source<br><br></pre></div><!--ENDSCRIPT--><br>Edit: Cool, okay then, I'll use this from now &#111;n, thanks man.

This topic is closed to new replies.

Advertisement