benwad
benwad

Reputation: 6594

Illegal call to non-static member function (C++)?

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?

Upvotes: 5

Views: 31967

Answers (7)

Farway
Farway

Reputation: 811

It can be useful to have a class containing a collection of functions, without any data members, if you don't want to expose the helper-functions.
Otherwise it would be more practical to use a namespace to collect these functions in.
Example:

class Solvers
{
public:
  void solve_a(std::vector<int> data);
  void solve_b(std::vector<int> data, int value);
private:
  int helper_a(int a, int b);
}

But a class needs to be initialised before use.
The simplest way to make these functions usable would be to mark them static in the class:
static void solve_a(std::vector<int> data);
Then the member-functions can be used as:
Solver::solve_a(my_vector);

Another way would be to initialise the class before using:
Solver solver;
solver.solve_a(my_vector);

And the third method, not mentioned before, is by default initialising it during use:
Solver().solve_a(my_vector);

Upvotes: 0

smocoder
smocoder

Reputation: 226

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 );
}

Upvotes: 0

Didier Trosset
Didier Trosset

Reputation: 37427

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.

Upvotes: 11

catchmeifyoutry
catchmeifyoutry

Reputation: 7349

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).

Upvotes: 1

Patrice Bernassola
Patrice Bernassola

Reputation: 14416

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).

Upvotes: 0

Nick Lewis
Nick Lewis

Reputation: 4230

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?

Upvotes: 0

Arkaitz Jimenez
Arkaitz Jimenez

Reputation: 23168

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(

Upvotes: 5

Related Questions