简体   繁体   English

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

[英]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: 屏幕的“地图”在文件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. ThreeDCubeGame.cpp处理大部分与地图有关的事情,但播放器(和键盘输入)由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中的这个函数:

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". 但是,当我编译它时,我收到警告“错误C2352:'ThreeDCubeGame :: GetMapEntry':非静态成员函数的非法调用”。 Is this something to do with the scope of the variables? 这与变量的范围有关吗? Is it fixable without redesigning all the code? 如果不重新设计所有代码,它是否可以修复?

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. 没有用于调用该函数的对象。

GetMapEntry is not static so you can't call it without an object of the type ThreeDCubeGame. GetMapEntry不是static因此如果没有ThreeDCubeGame类型的对象,则无法调用它。

Alternatives: 备择方案:
-Make GetMapEntry static: static inline char GetMapEntry -Make GetMapEntry static: static inline char GetMapEntry
-Create an instance of ThreeDCubeGame and do instance.GetMapEntry( - 创建ThreeDCubeGame的实例并执行instance.GetMapEntry(

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

You are trying to call a class method. 您正在尝试调用类方法。 Is that what you intend? 这是你想要的吗? Or do you mean for GetMapEntry to be an instance method? 或者你的意思是GetMapEntry是一个实例方法? 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 . 如果它是实例方法,则需要使用ThreeDCubeGame实例调用它。 Also, is GetMapEntry even a member of a class? 另外, GetMapEntry甚至是一个类的成员吗?

The error indicates that your are calling the GetMapEntry function as a static one whereas you have declare it as a member function. 该错误表示您正在将GetMapEntry函数作为静态函数调用,而您已将其声明为成员函数。 You need to: 你需要:

  • 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函数声明为static(在内联之前添加静态并使m_acMapData也为静态)。

You're missing the "static" keyword. 你错过了“static”关键字。

// .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. 如果您只想要一个独特的游戏区,还有其他选项:您可以将Playfield设为单个,将其转换为命名空间或使用全局函数。 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): 如果您需要多个游戏区域和/或想要以多线程方式安全地玩游戏和/或想要以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 );
}

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 非法调用非静态成员函数 - illegal call of non-static member function C ++错误C2352:&#39;CSchedulerDlg :: Select&#39;:非法调用非静态成员函数 - C++ error C2352: 'CSchedulerDlg::Select' : illegal call of non-static member function Qt c++嵌套类/解决非静态成员函数非法调用 - Qt c++ nested classes / solve illegal call of non-static member function 用struct&wifstream非法调用非静态成员函数 - Illegal call of non-static member function with struct & wifstream 数据库。 错误C2352:非法调用非静态成员函数 - Databases. error C2352: illegal call of non-static member function 错误C2352非法调用非静态成员函数 - error C2352 illegal call of non-static member function 错误C2352:非法调用非静态成员函数 - Error C2352: illegal call of non-static member function 让静态成员函数在 C++ 中调用非静态成员 std::function 的正确方法是什么? - What's the correct way to let the static member function call a non-static member std::function in c++? c ++错误:在没有对象参数的情况下调用非静态成员函数 - c++ error: call to non-static member function without an object argument C++ 线程“调用不带对象参数的非静态成员函数” - C++ Thread "Call to non-static member function without an object argument"
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM