views:

605

answers:

6

Hi

I'm developing a game which is based around the user controlling a ball which moves between areas on the screen. The 'map' for the screen is defined in the file ThreeDCubeGame.cpp:

char m_acMapData[MAP_WIDTH][MAP_HEIGHT];

The ThreeDCubeGame.cpp handles most of the stuff to do with the map, but the player (and keyboard input) is controlled by ThreeDCubePlayer.cpp. When a player moves into a new map cell, the game will have to check the contents of that cell and act accordingly. This function in ThreeDCubeGame.cpp is what I am trying to use:

inline char GetMapEntry( int iMapX, int iMapY ) { return m_acMapData[iMapX][iMapY]; }

So, in order to check whether the player is allowed to move into a map cell I use this function call from ThreeDCubePlayer.cpp:

if (ThreeDCubeGame::GetMapEntry(m_iMapX+MAP_OFF_X, m_iMapY+MAP_OFF_Y) == ' ')
{
// do stuff
}

But, when I compile this, I get the warning "error C2352: 'ThreeDCubeGame::GetMapEntry' : illegal call of non-static member function". Is this something to do with the scope of the variables? Is it fixable without redesigning all the code?

+3  A: 

GetMapEntry is not static so you can't call it without an object of the type ThreeDCubeGame.

Alternatives:
-Make GetMapEntry static: static inline char GetMapEntry
-Create an instance of ThreeDCubeGame and do instance.GetMapEntry(

Arkaitz Jimenez
Thanks for the answer.In my program ThreeDCubePlayer is an instance within ThreeDCubeGame - does this mean I can create an instance of ThreeDCubeGame within ThreeDCubePlayer that refers to the same 2-dimensional array?
benwad
You could use ThreeDCubePlayer.GetMapEntry( or this->GetMapEntry( from the inside.
Arkaitz Jimenez
A: 

You are trying to call a class method. Is that what you intend? Or do you mean for GetMapEntry to be an instance method? If it's a class method, it needs to be marked static. If it's an instance method, you need to call it with an instance of ThreeDCubeGame. Also, is GetMapEntry even a member of a class?

Nick Lewis
A: 

The error indicates that your are calling the GetMapEntry function as a static one whereas you have declare it as a member function. You need to:

  • call it via an instance of ThreeDCubeGame: threedcubegameinstance.GetMapEntry(),
  • declare the GetMapEntry function as static (add a static before inline and make m_acMapData static too).
Patrice Bernassola
A: 

ThreeDCubeGame is a class, not an instance, thus you can only use it to access static members (that is, member function with the keyword static) You have to instantiate an object of this class to use non-static members

ThreeDCubeGame map;
...
map.GetMapEntry(iMapX, iMapY).
catchmeifyoutry
+3  A: 
class A {
  int i;
public:
  A(): i(0) {}
  int get() const { return i; }
};

int main() {
  A a;
  a.get();  // works
  A::get(); // error C2352
}

There's no object to call the function with.

Didier Trosset
A: 

You're missing the "static" keyword.

// .h
class Playfield
{
public: 
  static char GetTile( int x, int y ); 
  // static on a method means no 'this' is involved
};

// .cpp
static char tiles[10][10] = {}; 
// static on vars in .cpp prevents access from outside this .cpp

char Playfield::GetTile( int x, int y )
{
  // handle invalid args

  // return tile
  return tiles[x][y];
}

There's other options if you want only one unique playfield: You can make Playfield a singleton, turn it into a namespace or use global functions. The result is the same from the caller's point of view.

On a side note: Since all of these use a static and/or global variable it's inherently not thread-safe.

If you require multiple playfields and/or want to play safe with multi-threadding and/or want to absolutely do it in an OOP fashion, you will need an instance of Playfield to call the function on (the 'this' pointer):

class Playfield
{
public:
   char GetTile( int x, int y ) const { return this->tiles[x][y]; } 
   // you can omit 'this->', but it's inherently present because
   // the method is not marked as static 
public:
   Playfield() 
   { /*you will have to initialize 'this->tiles' here because 
       you cannot use the struct initializer '= {}' on member vars*/ }

private:
   char tiles[10][10];
};

The calling code would use Playfield like this:

void main()
{
  // static version 
  char tile11 = Playfield::GetTile( 1, 1 );

  // non-static version
  Playfield myPlayfield;
  char tile12 = myPlayfield.GetTile( 1, 2 );
}
smocoder