Welcome, Guest. Please login or register.
Did you miss your activation email?

Login with username, password and session length

 
Advanced search

879282 Posts in 32974 Topics- by 24361 Members - Latest Member: Raiyumi

May 23, 2013, 05:24:07 PM
TIGSource ForumsDeveloperTechnical (Moderators: Glaiel-Gamer, ThemsAllTook)Need help with objects and classes.
Pages: 1 2 [3] 4
Print
Author Topic: Need help with objects and classes.  (Read 2986 times)
Netsu
Level 10
*****



View Profile WWW
« Reply #30 on: November 29, 2010, 02:24:35 AM »

For example my pointers are declared in IO.h between namespace IO { } as

static SDL_Surface      *mMainScreen   = NULL;
static SDL_Surface              *mGameWorld     = NULL;

removing static results in :

main.obj : error LNK2005: "struct SDL_Surface * IO::mMainScreen" (?mMainScreen@IO@@3PAUSDL_Surface@@A) already defined in IO.obj

I think your problem is that your are INITIALISING your pointer in the header file. This is wrong. I also don't see a reason for them to be static. You should only declare the pointer in the IO.h file (so don't assign NULL to them there) and then in a corresponding IO.cpp file (you should have one) you do this:

Code:
namespace IO
{
SDL_Surface *mMainScreen = NULL;
SDL_Surface              *mGameWorld     = NULL;
}

The error occurs because you're linking the IO.h file in multiple .cpp files, and thus you get multiple definitions of those pointers. The header files should only contain declarations of functions and variables, so that any .cpp file you link it to would know of it's existence. But the actual definition/initialisation should be in only one .cpp file that is later linked into the program as an .o/.obj file.
Logged

ASnogarD
Level 1
*



View Profile
« Reply #31 on: November 29, 2010, 03:20:46 AM »

I tried removing the = NULL assigning, but it wont let me remove the static keyword ( I think merely creating a pointer to a surface is actually assigning it, assigning NULL to it initially just ensures it doesnt access a forbidden area of memory).

I tried moving the whole lot to the IO.cpp but then the classes outside IO dont know about the pointers to the surfaces.

I tried creating a SDL_Surface object called mMainScreen in the IO.h file , and then a pointer to SDL_Surface *mMainScreen in the IO.cpp but the compiler told me there was no suitable conversion from a mMainScreen to mMainScreen*.

I am posting the code to the IO and World classes if that will help.

This is my IO.h
Code:

#ifndef IO_H_
#define IO_H_

#include<iostream>
#include<fstream>
#include<sstream>
#include<ctime>    // For time()
#include<cstdlib>  // For srand() and rand()
#include<math.h>   // for math function like square root and cosine.
#include<vector>

#include"SDL.h"
#include"SDL_ttf.h"
#include"SDL_image.h"

#include"timer.h"
#include"world.h"

/////////////////////////////////////////////////////////////////////////////////////////
//
//
// IO CLASS - provides via SDL access to the PC hardware, and provides some utility
// functions such as draw_text.
//
//



namespace IO
{
///////////////////////////////////////////////////////////////////////
// pointers to the surfaces

static SDL_Surface *mMainScreen = NULL;
static SDL_Surface *mGameWorld = NULL;
static SDL_Surface *mPlayer = NULL;
static SDL_Surface *mAli = NULL;

///////////////////////////////////////////////////////////////////////
// text colour

static SDL_Color textColor = { 0, 0, 255 };

///////////////////////////////////////////////////////////////////////
// pointer to the font

static TTF_Font *mFont = NULL;

///////////////////////////////////////////////////////////////////////
//  counters and setter ints

static unsigned int msgBufferSize = 0;
static unsigned int msgStart = 0;
static unsigned int numberMsgToShow = 27;


///////////////////////////////////////////////////////////////////////
// IO Functions

int init();
void clean_up();
void draw_text( std::string msg, int x, int y );



SDL_Surface *load_image( std::string filename );
void apply_surface( int x, int y, SDL_Surface* source, SDL_Surface* destination, SDL_Rect* clip );
void draw( int x, int y, int subject, SDL_Rect* clip );
bool load_files();

void update_screen();

////////////////////////////////////////////////////////////////////////
// Console control functions

void report_screen( std::string msg );
void show_message();

void set_msgStart_increase();
void set_msgStart_decrease();

void set_tileCounter_inc();
void set_tileCounter_dec();

};

#endif

This is my IO.cpp
Code:

#include"io.h"
#include"global.h"

using std::vector;

/////////////////////////////////////////////////////////////////////////////////////////
//
//
// IO CLASS - provides via SDL access to the PC hardware, and provides some utility
// functions such as draw_text.
//
// global.h is a header file that defines constants and enums that are needed by all
// the classes.
//
//

////////////////////////////////////////////////////////////////////
// Local Data

static vector<std::string> msgBuffer;

static unsigned int lastTextX = 30; // provide the x value for the report function to pass to draw_text
static unsigned int lastTextY = 30; // proved the y value and is incremented to allow for a newline for each report

static unsigned int msgCount = 0; // counts the number of messages stored , used for limiting the number of messages displayed

static unsigned int tilesCounter = 0;


///////////////////////////////////////////////////////////////////
// IO Functions

int IO::init()
{

// Initialises the entire main SDL library,
// note it is possible to init portions individually
if ( SDL_Init(SDL_INIT_EVERYTHING) == -1 )
{
std::cerr << "Error init SDL_INIT_EVERYTHING" << std::endl;
return -1;
}

// Sets the main screen where all the surfaces will be blitted to,
// this sets the size and mode of the screen.
mMainScreen = SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_SWSURFACE );

if ( mMainScreen == NULL )
{
std::cerr << "Error setting mainscreen surface" << std::endl;
return -1;
}

// Initialises the TTF sub library
if ( TTF_Init() == -1 )
{
std::cerr << "Error init TTF_Init" << std::endl;
return -1;
}

// Sets the title of the window
SDL_WM_SetCaption ( " Kickin' Sticks WIP  --- Average Frames Per Second: ", NULL );

// open the font
mFont = TTF_OpenFont( "GFX/exprswy free.ttf", 16);
if ( mFont == NULL )
{
std::cerr << "Error loading exprswy free.ttf" << std::endl;
return -1;
}
// Now the program can report whats happening via the report_screen func

//////////////////////////////////////////////////////
//
// load the graphic sprite and tilesheet files
// Intend to expand this to a resource manager
// if the files become too much when using
// audio
//

report_screen( "This report was removed before posting to TIG" );
report_screen( "---------------------------------------------" );
report_screen( "SDL Init : OK" ); // SDL and TTF are assumed to have been init properly
report_screen( "TTF_Init : OK" ); // otherwise text display wouldnt be possible.
report_screen( "loading resources... " );

SDL_Delay( 800 );  // added for effect , not required at all.

if ( load_files() == false )
{
return -1;
}

report_screen( "Init and Load completed, starting game...." );


SDL_Delay( 800 ); // added for effect , not required at all.

// If everything initialises properly return true to the caller.
return 0;
}


void IO::clean_up()
{
report_screen( "Clean up function called..."); // Just to see the function IS getting called
SDL_Delay( 800 ); // gimme some time to see the report will ya :P

SDL_FreeSurface ( mGameWorld );
SDL_FreeSurface ( mPlayer );
SDL_FreeSurface ( mAli );

// Function frees up surfaces used, then shuts down the TTF and SDL libraries.
TTF_CloseFont( mFont );
TTF_Quit();
SDL_Quit();

}

void IO::draw_text( std::string msg, int x, int y )
{

SDL_Rect coordinates;
coordinates.x = (int)x;
coordinates.y = (int)y;
SDL_Surface *message = NULL;
message = TTF_RenderText_Solid( mFont, msg.c_str(), textColor );

SDL_BlitSurface( message, NULL, mMainScreen, &coordinates );

SDL_FreeSurface( message );

}


void IO::update_screen()
{

SDL_Flip( mMainScreen );

}



SDL_Surface *IO::load_image( std::string filename )
{
///////////////////////////////////////////////////////////////////////
// This function takes a graphics file to be loaded , it puts it on a
// temporary surface then uses SDL_DisplayFormat to optimise the
// image and then return the optimised image back to the caller.
//

SDL_Surface* loadedImage = NULL;
SDL_Surface* optimisedImage = NULL;

loadedImage = IMG_Load ( filename.c_str() );

if ( loadedImage != NULL )
{
optimisedImage = SDL_DisplayFormat( loadedImage );
SDL_FreeSurface( loadedImage );
if ( optimisedImage != NULL )
{
// Change the ->format RGB values to the colour that is the suppose to be transparent
// Currently its a purple colour.
SDL_SetColorKey( optimisedImage, SDL_SRCCOLORKEY,
SDL_MapRGB( optimisedImage->format, 0xA3, 0x4D, 0xFD ) );
}
}

///////////////////////////////////////////////
// Reports which file was loaded
// Could be improved with IO file checks

std::string buffer;
std::stringstream ss;

ss << "Loaded : " << filename ;

buffer = ss.str();

report_screen( buffer );

// End report block
///////////////////////////////////////////////

return optimisedImage;
}

void IO::apply_surface( int x, int y, SDL_Surface* source, SDL_Surface* destination, SDL_Rect* clip = NULL )
{
SDL_Rect offset;

offset.x = x;
offset.y = y;

SDL_BlitSurface( source, clip, destination, &offset );
}

void IO::draw( int x, int y, int subject, SDL_Rect *clip )
{
SDL_Rect clips = *clip;

if ( subject == DRAW_TILE )
{ apply_surface( x, y, mGameWorld, mMainScreen,  &clips ); }
}

bool IO::load_files()
{

mGameWorld = load_image( "GFX/tiles.png" );

if ( mGameWorld == NULL )
{
return false;
}

mPlayer = load_image( "GFX/stick.png" );

if ( mPlayer == NULL )
{
return false;
}

mAli = load_image( "GFX/kickassest.png" );

if ( mAli == NULL )
{
return false;
}

return true;
}

////////////////////////////////////////////////////////////////
// Console Control functions

void IO::report_screen( std::string msg )
{

std::string pushMsg = msg; // put the parameter string into a temp variable

msgBuffer.push_back( pushMsg ); // add the string in the temp variable to the vector

msgCount ++;  // increment the msg counter ( temp check to count messages generated )

if ( msgCount > numberMsgToShow ) // this IF basically checks to see if the
{ // number of msgs is more than the number it should
msgStart ++; // show at one time, if it is it increments from where
} // the show_message start listing the vector of strings,
// IE messages ( limited to 27 msgs on screen at 1 time )
show_message();

}

void IO::show_message()
{
// SDL_FillRect( SDL_GetVideoSurface(), NULL, 0 ); // Clear the screen ( paint it black - warning: slow )

/////////////////////////////////////////////////////////////////////////
// Loop to go through the vector of messages and print them to screen

unsigned int tTxtLimit = numberMsgToShow + msgStart;

if ( tTxtLimit > msgBuffer.size() ) { tTxtLimit = msgBuffer.size(); }

for ( unsigned int i = 0 + msgStart; i < tTxtLimit; i++ ) // note msgStart here
{
std::string tMsg = msgBuffer[i];

draw_text( tMsg, lastTextX, lastTextY );
lastTextY += 20;

} // end of for loop

// End of loop
//
/////////////////////////////////////////////////////////////////////////

lastTextY = 30; // Resets the y value ready for the next call to report


////////////////////////////////////////////////////////////////////////
// Temp block to report the number of messages stored in the msgBuffer

std::string buffer;
std::stringstream ss;

ss << "Number of Messages [ " << msgCount << " ] " << " [ " << tilesCounter << " ] " ;

buffer = ss.str();

draw_text( buffer, SCREEN_WIDTH - 270, SCREEN_HEIGHT -25 );

// End block
////////////////////////////////////////////////////////////////////////

update_screen(); // Updates the screen so the messages get displayed
}


void IO::set_msgStart_increase()
{
if ( msgStart >= msgBuffer.size() ) { msgStart = msgBuffer.size(); } else msgStart ++;

show_message();
}

void IO::set_msgStart_decrease()
{

if ( msgStart <= 0 ) { msgStart = 0; } else msgStart -- ;

show_message();
}


void IO::set_tileCounter_inc()
{
tilesCounter++;
show_message();
}

void IO::set_tileCounter_dec()
{
tilesCounter--;
show_message();
}
//
// End of IO class
//
//////////////////////////////////////////////////////////////////////////////////////////////





This is my World.h
Code:
#ifndef WORLD_H_
#define WORLD_H_

#include"IO.h"
#include"global.h"

class Tile;


namespace K_WORLD
{
///////////////////////////////////////////////////////////////
// Pointer to tiles and a array of SDL_Rects holding clip data

static std::vector<Tile*> mTiles;

static SDL_Rect clips[ TILE_TYPES ];


///////////////////////////////////////////////////////////////
// K_World Functions

bool set_tiles();

void show_tiles();


void clean_tiles();
void clip_tiles();




};
#endif

This is my World.cpp
Code:
#include"world.h"

#include"tile.h"


/////////////////////////////////////////////////////////////////////////////
// K_WORLD Functions

bool K_WORLD::set_tiles()
{
int x = 0, y = 0;

std::ifstream map( "GFX/lazy.map" );

if ( map == NULL )
{
return false;
}

IO::report_screen( "Loading Tile Map ...." );

for ( int t = 0; t < TOTAL_TILES; t++ )
{
int tileType = -1;
map >> tileType;

if( map.fail() == true )
{
map.close();
return false;
}

if( ( tileType >=0 ) && ( tileType < TILE_TYPES ) )
{
mTiles.push_back( new Tile ( x , y , tileType ) );
IO::set_tileCounter_inc();
}

else
{
map.close();
return false;
}

x += TILE_WIDTH;

if( x >= LEVEL_WIDTH )
{
x = 0;
y += TILE_HEIGHT;
}

if( ( tileType >=4 ) && ( tileType < TILE_TYPES ) )
{
mTiles[ t ]->mTileState = TILE_COLLIDE ;

} else  mTiles[ t ]->mTileState = TILE_AVAILABLE ;

/*

///////////////////////////////////////////////////////////////////////
// Temp block to report info on the tile as its being created

std::string buffer;
std::stringstream ss;

ss << "Tile [ " << t << " ] Type [ " << tileType << " ] X [ " << x << " ] Y [ " << y << " ] State [ " << mTiles[ t ]->get_state();

buffer = ss.str();

IO::report_screen( buffer );

// end tile report block
//////////////////////////////////////////////////////////////////////

*/
}

map.close();

return true;
}

void K_WORLD::show_tiles()
{
for( int t = 0; t < TOTAL_TILES; t++ )
{

IO::draw( mTiles[ t ]->mTileXpos, mTiles[ t ]->mTileYpos, DRAW_TILE ,&clips[ mTiles[ t ]->mTileType ] );

// IO::apply_surface(  mTiles[ t ]->mTileXpos, mTiles[ t ]->mTileYpos, IO::mGameWorld, IO::mMainScreen ,&clips[ mTiles[ t ]->mTileType ] );

}
}


void K_WORLD::clean_tiles ()
{
int tmpCount = 0;

IO::report_screen( "Clean Tiles function called ..." );

for( std::vector<Tile*>::iterator i = mTiles.begin(); i != mTiles.end(); ++i )
{
delete *i ;
IO::set_tileCounter_dec();

}

IO::report_screen( "Clean Tiles function completed" );
SDL_Delay ( 400 );
}

void K_WORLD::clip_tiles()
{

IO::report_screen( "Clipping World Tiles... " );

// Clip the tile sprites for the level

    clips[ TILE_RED ].x = 0;
    clips[ TILE_RED ].y = TILE_HEIGHT * 3;
    clips[ TILE_RED ].w = TILE_WIDTH;
    clips[ TILE_RED ].h = TILE_HEIGHT;

    clips[ TILE_GREEN ].x = TILE_WIDTH;
    clips[ TILE_GREEN ].y = TILE_HEIGHT * 3;
    clips[ TILE_GREEN ].w = TILE_WIDTH;
    clips[ TILE_GREEN ].h = TILE_HEIGHT;

    clips[ TILE_BLUE ].x = TILE_WIDTH * 2;
    clips[ TILE_BLUE ].y = TILE_HEIGHT * 3;
    clips[ TILE_BLUE ].w = TILE_WIDTH;
    clips[ TILE_BLUE ].h = TILE_HEIGHT;

    clips[ TILE_TOPLEFT ].x = 0;
    clips[ TILE_TOPLEFT ].y = 0;
    clips[ TILE_TOPLEFT ].w = TILE_WIDTH;
    clips[ TILE_TOPLEFT ].h = TILE_HEIGHT;

    clips[ TILE_LEFT ].x = 0;
    clips[ TILE_LEFT ].y = TILE_HEIGHT;
    clips[ TILE_LEFT ].w = TILE_WIDTH;
    clips[ TILE_LEFT ].h = TILE_HEIGHT;

    clips[ TILE_BOTTOMLEFT ].x = 0;
    clips[ TILE_BOTTOMLEFT ].y = TILE_HEIGHT * 2;
    clips[ TILE_BOTTOMLEFT ].w = TILE_WIDTH;
    clips[ TILE_BOTTOMLEFT ].h = TILE_HEIGHT;

    clips[ TILE_TOP ].x = TILE_WIDTH;
    clips[ TILE_TOP ].y = 0;
    clips[ TILE_TOP ].w = TILE_WIDTH;
    clips[ TILE_TOP ].h = TILE_HEIGHT;

    clips[ TILE_CENTER ].x = TILE_WIDTH;
    clips[ TILE_CENTER ].y = TILE_HEIGHT;
    clips[ TILE_CENTER ].w = TILE_WIDTH;
    clips[ TILE_CENTER ].h = TILE_HEIGHT;

    clips[ TILE_BOTTOM ].x = TILE_WIDTH;
    clips[ TILE_BOTTOM ].y = TILE_HEIGHT * 2;
    clips[ TILE_BOTTOM ].w = TILE_WIDTH;
    clips[ TILE_BOTTOM ].h = TILE_HEIGHT;

    clips[ TILE_TOPRIGHT ].x = TILE_WIDTH * 2;
    clips[ TILE_TOPRIGHT ].y = 0;
    clips[ TILE_TOPRIGHT ].w = TILE_WIDTH;
    clips[ TILE_TOPRIGHT ].h = TILE_HEIGHT;

    clips[ TILE_RIGHT ].x = TILE_WIDTH * 2;
    clips[ TILE_RIGHT ].y = TILE_HEIGHT;
    clips[ TILE_RIGHT ].w = TILE_WIDTH;
    clips[ TILE_RIGHT ].h = TILE_HEIGHT;

    clips[ TILE_BOTTOMRIGHT ].x = TILE_WIDTH * 2;
    clips[ TILE_BOTTOMRIGHT ].y = TILE_HEIGHT * 2;
    clips[ TILE_BOTTOMRIGHT ].w = TILE_WIDTH;
    clips[ TILE_BOTTOMRIGHT ].h = TILE_HEIGHT;

// Temp clips for the hole and the explosion

clips[ TILE_HOLE ].x = TILE_WIDTH;
    clips[ TILE_HOLE ].y = TILE_HEIGHT * 3;
    clips[ TILE_HOLE ].w = TILE_WIDTH;
    clips[ TILE_HOLE ].h = TILE_HEIGHT;

clips[ TILE_EXPLOSION ].x = TILE_WIDTH;
    clips[ TILE_EXPLOSION ].y = TILE_HEIGHT * 4;
    clips[ TILE_EXPLOSION ].w = TILE_WIDTH;
    clips[ TILE_EXPLOSION ].h = TILE_HEIGHT;
}

The code works in the current form which comments out :

// IO::apply_surface(  mTiles[ t ]->mTileXpos, mTiles[ t ]->mTileYpos, IO::mGameWorld, IO::mMainScreen ,&clips[ mTiles[ t ]->mTileType ] );

and uses the makeshift function :

IO::draw( mTiles[ t ]->mTileXpos, mTiles[ t ]->mTileYpos, DRAW_TILE ,&clips[ mTiles[ t ]->mTileType ] );

... so I am assuming the clipping and accessing the location and type, plus all the mapping worked as intended and only the pointers are the issue.

Logged

Somethings are painfully obvious, others must be made obvious... painfully.
Netsu
Level 10
*****



View Profile WWW
« Reply #32 on: November 29, 2010, 03:30:41 AM »

Have you trued removing both static and NULL from IO.h and putting the code I posted in the IO.cpp? What happened?
Logged

ASnogarD
Level 1
*



View Profile
« Reply #33 on: November 29, 2010, 03:58:40 AM »

I did as you said, but to make double sure I did it again before this reply...

in IO.h the pointers look like :

namespace IO

{

   SDL_Surface      *mMainScreen   ;
   SDL_Surface      *mGameWorld   ;

... function prototypes here
}

in IO.cpp

namespace IO
{
   SDL_Surface      *mMainScreen   = NULL;
   SDL_Surface      *mGameWorld   = NULL;
}

result when compiling:

io.cpp(32): error C2086: 'SDL_Surface *IO::mMainScreen' : redefinition
io.h(35) : see declaration of 'IO::mMainScreen'

result is the same if I remove the = NULL assignment in IO.cpp.
Logged

Somethings are painfully obvious, others must be made obvious... painfully.
Netsu
Level 10
*****



View Profile WWW
« Reply #34 on: November 29, 2010, 05:30:36 AM »

Ok, sorry, it'smy mistake. In the .cpp file you should only assign a value, not define the variable again:

in IO.cpp
Code:
namespace IO
{
   *mMainScreen   = NULL;
   *mGameWorld   = NULL;
}
Logged

Overkill
Level 3
***


Andrew G. Crowell

overkill9999@gmail.com Minimum+Overkill
View Profile WWW Email
« Reply #35 on: November 29, 2010, 05:40:19 AM »

Netsu: Not quite, you definitely need the definition in your cpp file. But you need to use extern in your header, so that the other files know of the variable's declaration but won't allocate their own address for that variable. Otherwise, you'll get a nasty linker error.

Also you can't put statements outside of functions, you can only give initializers for declarations. If that were possible, *mMainScreen is not the same as mMainScreen, and would be assigning the dereference of the uninitialized mMainScreen. Probably not desirable! D:

So use "extern" in the header where you are declaring the variable's existence to other code, and leave out "extern" in the .cpp where you are actually defining the varaible.

Code:
namespace IO
{

   extern SDL_Surface      *mMainScreen;
   extern SDL_Surface      *mGameWorld;

... function prototypes here
}

in IO.cpp

namespace IO
{
   SDL_Surface      *mMainScreen   = NULL;
   SDL_Surface      *mGameWorld   = NULL;
}

Also static directly inside namespaces (or directly in the global namespace) means that the function/declaration only exists in that file, which makes them of limited use, especially if you're using them in a header. Just leave out the static unless you're doing it in your .cpp file to hide functions you don't want called from other code.

Static inside of classes however, has the meaning you'd expect:

Code:
class IO
{

   static SDL_Surface      *mMainScreen;
   static SDL_Surface      *mGameWorld;

... method prototypes and attribute declarations here
};

in IO.cpp

SDL_Surface      *IO::mMainScreen   = NULL;
SDL_Surface      *IO::mGameWorld   = NULL;
« Last Edit: November 29, 2010, 05:53:36 AM by Overkill » Logged

ASnogarD
Level 1
*



View Profile
« Reply #36 on: November 29, 2010, 05:48:43 AM »

Thank you, the use of :

Code:
namespace IO
{

   extern SDL_Surface      *mMainScreen;
   extern SDL_Surface      *mGameWorld;

... function prototypes here
}

in IO.cpp

namespace IO
{
   SDL_Surface      *mMainScreen   = NULL;
   SDL_Surface      *mGameWorld   = NULL;
}

worked a charm, the tiles rendered using apply_surface, means I now longer need the supporting intermediate draw function.

Thanks for that Overkill, and thanks Netsu for having patiance with a noob  Beer!
Logged

Somethings are painfully obvious, others must be made obvious... painfully.
Netsu
Level 10
*****



View Profile WWW
« Reply #37 on: November 29, 2010, 05:51:20 AM »

Netsu: Not quite, you need the definition in your cpp file. But you need to use extern in your header, so that  other files know of the variable's declaration but won't allocate their own address for that variable.

You can't put statements outside of functions, you can only give initializers for declarations. Also, Netsu, if that were possible, *mMainScreen is not the same as mMainScreen, and would be assigning the dereference of the uninitialized mMainScreen. Probably not desirable! D:

I always thought that extern works more or less the same way as the code I suggested. I used both methods with success, but you're probably right, and extern is the 'correct' way.

And you're right... if I'm not declaring the pointer in the .cpp file I should not use the asterix because I'm dereferencing it then. I overlooked it :C
Logged

Average Software
Level 10
*****

Fleeing all W'rkncacnter


View Profile WWW Email
« Reply #38 on: November 29, 2010, 05:53:06 AM »

Also static directly inside namespaces (or directly in the global namespace) means that the function/declaration only exists in that file, which makes them of limited use,

It should be noted that this use of static is actually deprecated in C++, you're supposed to use the anonymous namespace instead.  It will never actually go away (it's needed for C compatibility) but you should try to avoid it in new code.
Logged

Franchise - The restaurant wars begin!

What would John Carmack do?
BorisTheBrave
Level 10
*****


View Profile WWW
« Reply #39 on: November 29, 2010, 05:57:46 AM »

Netsu, your advice was pretty poor, please don't defend it. Static in that context might look like it's working up until you realize you've managed to make two separate variables with the same name, one for each compilation unit.

Personally, I always use a classes with static members for globals, extern just seems hacky to me, as essentially it can break compilation unit encapsulation encapsulation.
Logged
Netsu
Level 10
*****



View Profile WWW
« Reply #40 on: November 29, 2010, 06:03:36 AM »

Netsu, your advice was pretty poor, please don't defend it. Static in that context might look like it's working up until you realize you've managed to make two separate variables with the same name, one for each compilation unit.

I'm not defending it, I just said it worked for me and I had no idea it is incorrect. I also didn't suggest static if this is what you mean.
Logged

ASnogarD
Level 1
*



View Profile
« Reply #41 on: November 29, 2010, 06:30:36 AM »

I was the one using STATIC, Netsu was trying to correct my mistakes I made.

 
Logged

Somethings are painfully obvious, others must be made obvious... painfully.
Average Software
Level 10
*****

Fleeing all W'rkncacnter


View Profile WWW Email
« Reply #42 on: November 29, 2010, 08:23:19 AM »

Personally, I always use a classes with static members for globals, extern just seems hacky to me, as essentially it can break compilation unit encapsulation encapsulation.

The class solution seems more hacky to me.  Just bury the data in a source file and provide accessors in a namespace.  This provides even better encapsulation, since the data isn't even declared in the header.
Logged

Franchise - The restaurant wars begin!

What would John Carmack do?
Klaim
Level 10
*****



View Profile WWW
« Reply #43 on: November 29, 2010, 09:03:23 AM »

I agree, in C++ using an empty class with static class is just overkill. You don't need that to "encapsulate" global functions. Use namespace instead. It's understandable that C# and Java and ActionScript do it differently because their namespace feature have nothing to do with the C++ one and there is no way to make global functions( in fact in ActionScript you can and personally I did).
Logged

http://www.klaimsden.net | Game : NetRush | Digital Story-Telling Technologies : Art Of Sequence
BorisTheBrave
Level 10
*****


View Profile WWW
« Reply #44 on: November 29, 2010, 09:35:46 AM »

The class solution seems more hacky to me.  Just bury the data in a source file and provide accessors in a namespace.  This provides even better encapsulation, since the data isn't even declared in the header.
Also fine. I just like the consistency that everything is in a class, and every C++ file is is named after the one class it defines. I guess it's a holdover from languages that force you do so.
Logged
Pages: 1 2 [3] 4
Print
Jump to:  

Theme orange-lt created by panic