#170104 - the-anonymous-coward - Mon Aug 31, 2009 7:27 am
Okay, so I know by reading around here that data in a header file in a no-no. However, I have been trying to compile multiple class source files that have constants and have ran into problems. I can't figure out how to create constant variable and separate it into a header and source file. The only way I have been able to get rid of the errors is with the code below, but I want to know how to properly do it. So, what should I do?
Code: |
#ifndef CONSTANTS_H
#define CONSTANTS_H
const int SCREEN_W = 400;
const int SCREEN_H = 275;
const int SCREEN_BPP = 32;
#endif
|
#170108 - eKid - Mon Aug 31, 2009 11:03 am
I usually use an enum for that kind of stuff.
Code: |
#ifndef STUFF_H
#define STUFF_H
enum {
SCREEN_W = 400,
SCREEN_H = 275,
SCREEN_BPP = 32
};
#endif
|
I think it would also be okay if you prefixed 'static' to those const int's.
#170110 - gauauu - Mon Aug 31, 2009 3:12 pm
Alternatively (but not necessarily better than the enum), traditionally, this has been one of the accepted uses of the preprocessor:
Code: |
#define SCREEN_W 400
|
#170115 - the-anonymous-coward - Mon Aug 31, 2009 7:08 pm
Ah, thanks. Works. So it's technically correct to include data in a header if it is in an enum?
Next problem is declaring pointers in a class header. The compiler doesn't seem to like:
Code: |
#ifndef WINDOW_H
#define WINDOW_H
#include <string>
#include "SDL/SDL.h"
using std::string;
class Window
{
public:
Window();
bool create();
void cleanup();
private:
//const int SCREEN_WIDTH = 400;
//const int SCREEN_HEIGHT = 275;
//const int SCREEN_BPP = 32;
SDL_Surface *background;
SDL_Surface *screen;
bool init();
SDL_Surface *loadImage( string );
void applySurface( int, int, SDL_Surface*, SDL_Surface* );
};
#endif
|
#170125 - elhobbs - Tue Sep 01, 2009 1:28 pm
error messages are helpful
#170131 - keldon - Tue Sep 01, 2009 4:44 pm
Make that a static const; otherwise you're telling the compiler that every instance of the class has a constant integer to store (do you catch my drift)?
Move that using std::string into the class, and for the code you've got you can do the following:
Code: |
// Get rid of the include below
// #include "SDL/SDL.h"
class SDL_Surface;
class Window
{
typedef std::string String; // Notice how I change it to your conventions
//
// ...
//
public:
static const int SCREEN_WIDTH = 400;
private:
SDL_Surface *load_image ( const String &file_name ); // Notice the const reference
};
|
Something like this might also be used instead of enumerations for a list of constants:
Code: |
static const int
SCREEN_WIDTH = 400,
SCREEN_HEIGHT = 275,
SCREEN_BPP = 32;
|
#170135 - the-anonymous-coward - Tue Sep 01, 2009 11:42 pm
I apologize, I will post the error messages asap.
Thanks, keldon. The static info helped. I will include the constants in this header now. There are a couple of things I don't understand, however. You are saying I should not include "SDL/SDL.h", right? Is that why you put
at the top? Does that allow me to use SDL_Surface without including the entire header? I also don't understand the use of const in the load_image function header. Here is a link to the code that I learned from and am adapting and separating into multiple files:
page:
http://lazyfoo.net/SDL_tutorials/lesson02/index.php
source:
http://lazyfoo.net/downloads/index.php?file=SDLTut_lesson02
#170136 - keldon - Wed Sep 02, 2009 1:13 am
Re: 'include "SDL/SDL.h"
Including anything in a header file means that anything that includes the header file also includes those files. Use forward declaration over includes where possible.
If a class <A> includes only pointer references to class <B> then only a forward declaration of <B> is needed.
Re: const reference (notice the &reference)
Your method has no need to modify the string, and copying the string results in a number of needless instructions. In this case it is best to avoid the unnecessary overhead, especially given that there is no good reasoning for doing so. This is not premature optimism, but rather copying the string (as was done in the Lazy Foo example) could be regarded as premature pessimism, which is another type of design flaw.
Whenever passing an object you will not modify that is larger than 4 bytes you will probably find that const references are the best choice.
---
However, the purpose of Lazy Foo's SDL tutorial site is to teach SDL and not C++. Experience (and some C++ design books) will tell you when to use a static class constant, namespace constant, enumeration or a function. For now, continue to focus on getting working prototypes that you can refine at a later time - you are making great progress!
#170166 - the-anonymous-coward - Sat Sep 05, 2009 1:01 am
Hey. Thanks a lot, keldon. I really appreciate the information, advice, and encouragement. I am actually replying from my cell phone. Going out of town. I would like to ask what design book you would recommend me reading later, when I need one?
#170173 - keldon - Sat Sep 05, 2009 4:05 pm
Off the top of my head I can think of the following:
- Effective C++
- More Effective C++
- Design Patterns by Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides
- Effective STL
There's a list we have on our work wiki, plus some others that others may suggest. I might add some stuff if I missed anything.
#170175 - the-anonymous-coward - Sat Sep 05, 2009 6:12 pm
Yeah, those are actually all on my wish list. Which should I start with. I read that... let me see, was it C++ CODING STANDARDS? ... anyway, I read that something similar to that title was really good. Any in particular I should start with? I always see EFFECTIVE C++ mentioned.
Also, your work wiki, is it private for the company's viewing only? I didn't see it at sigames.com
#170178 - keldon - Sat Sep 05, 2009 10:05 pm
It's a private wiki; but I think that Scott Meyer's list of 'important' C++ books pretty much covers the rest. You can also download Thinking In C++ for free!
Just for completion, here is the list of suggested reading on our wiki:
C/C++ Books
The C++ Programming Language, Bjarne Stroustrup, Addison Wesley
The Annotated C++ Reference manual, Margaret Ellis & Bjarne
Effective C++
More Effective C++
General programming books
The pragmatic programmer, Andrew Hunt ...
The practice of programming, Brian Kernighan ...
Programming pearls, Jon Bentley
Extreme programming explained, Kent Beck ...
Design patterns, Gamma / Help / Johnson ..
Refactoring, Martin Fowler
#170182 - the-anonymous-coward - Sun Sep 06, 2009 6:07 pm
Thanks!
Okay, I finally have a chance to post error messages. Here are the current ones:
Code: |
D:\MyProjects\C++\Internship>g++ -o graph.exe main.cpp window.cpp -lmingw32 -lSD
Lmain -lSDL
C:/mingw/bin/../lib/gcc/mingw32/3.4.5/../../../libSDLmain.a(SDL_win32_main.o): I
n function `console_main':
/Users/hercules/trunk/SDL-1.2/./src/main/win32/SDL_win32_main.c:246: undefined r
eference to `SDL_main'
collect2: ld returned 1 exit status
|
and here is my current header file:
Code: |
#ifndef WINDOW_H
#define WINDOW_H
#include <string>
#include "SDL/SDL.h"
using std::string;
class Window
{
public:
Window();
void cleanup();
private:
static const int
SCREEN_W = 400,
SCREEN_H = 275,
SCREEN_BPP = 32;
SDL_Surface* background;
SDL_Surface* screen;
void create();
void init();
SDL_Surface *loadImage( string );
void applySurface( int, int, SDL_Surface*, SDL_Surface* );
};
#endif
|
I plan to add the cleaner code that you made, keldon. But I want to get it working first. I am not sure where to look for the problem; the error message seems somewhat vague, but that's probably just my inexperience.
I am going to continue looking at the code. Let me know if you guys need anything else.
#170184 - the-anonymous-coward - Sun Sep 06, 2009 6:34 pm
Oh, and this code is embarrassing, but here is Window.cpp:
Code: |
//#include "SDL/SDL.h"
//#include <string>
#include "Window.h"
Window::Window()
{
background = NULL;
screen = NULL;
create();
}
void Window::init()
{
// initialize all SDL subsystems
if( SDL_Init( SDL_INIT_EVERYTHING ) == -1 )
{
//return false;
}
// set up the screen
screen = SDL_SetVideoMode( SCREEN_W, SCREEN_H, SCREEN_BPP, SDL_SWSURFACE );
// check for error in setting up screen
if( screen == NULL )
{
// return false;
}
// set the window caption
SDL_WM_SetCaption( "Graphing Window", NULL );
}
SDL_Surface* Window::loadImage( std::string filename )
{
// temporary storage for the image that's loaded
SDL_Surface* loadedImage = NULL;
// optimized image that will be used
SDL_Surface* optimizedImage = NULL;
// load the image
loadedImage = SDL_LoadBMP( filename.c_str() );
// if nothing went wrong in loading the image
if( loadedImage != NULL )
{
// create an optimized image
optimizedImage = SDL_DisplayFormat( loadedImage );
// free the old image
SDL_FreeSurface( loadedImage );
}
// return the optimized image
return optimizedImage;
}
void Window::applySurface( int x, int y, SDL_Surface* source, SDL_Surface* destination )
{
// make a temporary rectangle to hold the offsets
SDL_Rect offset;
// give the offsets to the rectangle
offset.x = x;
offset.y = y;
// blit the surface
SDL_BlitSurface( source, NULL, destination, &offset );
}
void Window::create()
{
init();
// load backgroung
background = loadImage( "prettyGraph1.bmp" );
// apply background to screen
applySurface( 0, 0, background, screen );
// update screen
if( SDL_Flip( screen ) == -1 )
{
//return false;
}
}
void Window::cleanup()
{
// free background
SDL_FreeSurface( background );
// release SDL
SDL_Quit();
}
|
Eww. Well, I will clean it up when I figure out the problem. Since it works in my test file that does all this in a single source file, I figure it must be something I don't understand about separating code into separate files, passing references or pointer, or returning them. Something along that line, and I am looking, but I don't see it. Over the past two days I have read all but the final chapter of BEGINNING C++ THROUGH GAME PROGRAMMING, a book I've had for a while. I understand all the concepts as I go through, but haven't applied them enough to see problems in my code.
#170189 - the-anonymous-coward - Sun Sep 06, 2009 10:17 pm
Ah, I figure it out. I forgot a must while working with SDL. The can't use "int main()" thing. Forgot "int main( int argc, char* args[] )". Now it works.