非法调用非静态成员函数(c++)?

时间:2022-09-01 16:53:49

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:

我正在开发一个基于用户控制一个球的游戏,它在屏幕上的区域之间移动。屏幕上的“map”定义在文件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:

ThreeDCubeGame。cpp处理大部分与地图有关的东西,但玩家(和键盘输入)由ThreeDCubePlayer.cpp控制。当玩家进入一个新的地图单元时,游戏将必须检查该单元格的内容并相应地采取行动。这个函数在ThreeDCubeGame。cpp是我想要使用的:

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:

因此,为了检查玩家是否被允许移动到地图单元格,我使用了来自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?

但是,当我编译这个时,我得到了一个警告“error C2352:‘ThreeDCubeGame::GetMapEntry’:非法调用非静态成员函数”。这与变量的范围有关吗?是否可以在不重新设计所有代码的情况下解决问题?

7 个解决方案

#1


9  

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.

没有对象可以调用函数。

#2


4  

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

GetMapEntry不是静态的,所以不能在没有ThreeDCubeGame的对象的情况下调用它。

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

选择:-使GetMapEntry静态:静态内联char GetMapEntry -创建一个ThreeDCubeGame的实例并执行instance.GetMapEntry(

#3


1  

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是一个类,而不是一个实例,因此您只能使用它来访问静态成员(即,带有关键字static的成员函数),您必须实例化这个类的一个对象来使用非静态成员。

ThreeDCubeGame map;
...
map.GetMapEntry(iMapX, iMapY).

#4


0  

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?

您正在尝试调用类方法。这是你想要的吗?或者你是说GetMapEntry是一个实例方法?如果它是一个类方法,它需要被标记为静态。如果是实例方法,您需要使用ThreeDCubeGame实例来调用它。另外,GetMapEntry是不是一个类的成员?

#5


0  

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:

这个错误指示您将GetMapEntry函数作为一个静态函数调用,而您已经将它声明为一个成员函数。你需要:

  • call it via an instance of ThreeDCubeGame: threedcubegameinstance.GetMapEntry(),
  • 通过ThreeDCubeGame的实例调用它:threedcubegameinstance.GetMapEntry(),
  • declare the GetMapEntry function as static (add a static before inline and make m_acMapData static too).
  • 将GetMapEntry函数声明为静态的(在内联前添加一个静态,并使m_acMapData静态)。

#6


0  

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.

如果您只需要一个独特的playfield,还有其他选项:您可以使playfield成为一个singleton,将它转换为一个名称空间或使用全局函数。从调用者的角度来看,结果是一样的。

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

如果您需要多个playfields和/或想要使用多线程和/或希望以OOP方式进行安全操作,您将需要一个Playfield实例来调用该函数(“this”指针):

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:

调用代码将使用这样的Playfield:

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

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

#7


0  

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:

如果您不想公开helper函数,那么拥有一个包含函数集合的类是很有用的,没有任何数据成员。否则,使用名称空间来收集这些函数将更加实际。例子:

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

但是需要在使用前初始化一个类。使这些函数可用的最简单的方法是在类中标记它们:静态void solve_a(std::vector 数据);然后,成员函数可以用作:Solver::solve_a(my_vector);

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

另一种方法是在使用前初始化类: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);

第三种方法,之前没有提到过,是默认的在使用期间初始化它:Solver().solve_a(my_vector);

#1


9  

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.

没有对象可以调用函数。

#2


4  

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

GetMapEntry不是静态的,所以不能在没有ThreeDCubeGame的对象的情况下调用它。

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

选择:-使GetMapEntry静态:静态内联char GetMapEntry -创建一个ThreeDCubeGame的实例并执行instance.GetMapEntry(

#3


1  

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是一个类,而不是一个实例,因此您只能使用它来访问静态成员(即,带有关键字static的成员函数),您必须实例化这个类的一个对象来使用非静态成员。

ThreeDCubeGame map;
...
map.GetMapEntry(iMapX, iMapY).

#4


0  

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?

您正在尝试调用类方法。这是你想要的吗?或者你是说GetMapEntry是一个实例方法?如果它是一个类方法,它需要被标记为静态。如果是实例方法,您需要使用ThreeDCubeGame实例来调用它。另外,GetMapEntry是不是一个类的成员?

#5


0  

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:

这个错误指示您将GetMapEntry函数作为一个静态函数调用,而您已经将它声明为一个成员函数。你需要:

  • call it via an instance of ThreeDCubeGame: threedcubegameinstance.GetMapEntry(),
  • 通过ThreeDCubeGame的实例调用它:threedcubegameinstance.GetMapEntry(),
  • declare the GetMapEntry function as static (add a static before inline and make m_acMapData static too).
  • 将GetMapEntry函数声明为静态的(在内联前添加一个静态,并使m_acMapData静态)。

#6


0  

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.

如果您只需要一个独特的playfield,还有其他选项:您可以使playfield成为一个singleton,将它转换为一个名称空间或使用全局函数。从调用者的角度来看,结果是一样的。

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

如果您需要多个playfields和/或想要使用多线程和/或希望以OOP方式进行安全操作,您将需要一个Playfield实例来调用该函数(“this”指针):

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:

调用代码将使用这样的Playfield:

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

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

#7


0  

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:

如果您不想公开helper函数,那么拥有一个包含函数集合的类是很有用的,没有任何数据成员。否则,使用名称空间来收集这些函数将更加实际。例子:

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

但是需要在使用前初始化一个类。使这些函数可用的最简单的方法是在类中标记它们:静态void solve_a(std::vector 数据);然后,成员函数可以用作:Solver::solve_a(my_vector);

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

另一种方法是在使用前初始化类: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);

第三种方法,之前没有提到过,是默认的在使用期间初始化它:Solver().solve_a(my_vector);