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

C++ 对非静态成员函数(C+;+;)的非法调用?,c++,scope,C++,Scope,我正在开发一个基于用户控制球的游戏,球在屏幕上各个区域之间移动。屏幕的“映射”在文件ThreeDCubeGame.cpp中定义: char m_acMapData[MAP_WIDTH][MAP_HEIGHT]; 3rdcubegame.cpp处理与地图有关的大部分内容,但播放器(和键盘输入)由3rdcubeplayer.cpp控制。当玩家移动到一个新的地图单元时,游戏必须检查该单元的内容并相应地采取行动。ThreeDCubeGame.cpp中的此函数正是我尝试使用的: inline char

我正在开发一个基于用户控制球的游戏,球在屏幕上各个区域之间移动。屏幕的“映射”在文件ThreeDCubeGame.cpp中定义:

char m_acMapData[MAP_WIDTH][MAP_HEIGHT];
3rdcubegame.cpp处理与地图有关的大部分内容,但播放器(和键盘输入)由3rdcubeplayer.cpp控制。当玩家移动到一个新的地图单元时,游戏必须检查该单元的内容并相应地采取行动。ThreeDCubeGame.cpp中的此函数正是我尝试使用的:

inline char GetMapEntry( int iMapX, int iMapY ) { return m_acMapData[iMapX][iMapY]; }
因此,为了检查播放器是否允许移动到地图单元格中,我使用ThreedCubeplyer.cpp中的以下函数调用:

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

但是,当我编译它时,我得到警告“错误C2352:'ThreeDCubeGame::GetMapEntry:非法调用非静态成员函数”。这和变量的范围有关吗?它不需要重新设计所有代码就可以修复吗?

GetMapEntry不是静态的,因此如果没有ThreeDCubeGame类型的对象,就不能调用它

备选方案:
-使GetMapEntry为静态:
静态内联字符GetMapEntry


-创建ThreeDCubeGame的实例并执行
instance.GetMapEntry(

您正试图调用一个类方法。这是您想要的吗?或者您的意思是将
GetMapEntry
作为一个实例方法吗?如果它是一个类方法,则需要将其标记为静态。如果它是一个实例方法,则需要使用
ThreeDCubeGame
的实例调用它。
GetMapEntry
甚至是对于类?

此错误表示您正在将
GetMapEntry
函数作为静态函数调用,而您已将其声明为成员函数。您需要:

  • 通过ThreeDCubeGame的实例调用它:
    threedcubegameinstance.GetMapEntry()
  • 将GetMapEntry函数声明为static(在内联之前添加一个static,并使m_acMapData也为static)

ThreeDCubeGame
是一个类,而不是一个实例,因此您只能使用它访问静态成员(即带有关键字
static
的成员函数) 必须实例化此类的对象才能使用非静态成员

ThreeDCubeGame map;
...
map.GetMapEntry(iMapX, iMapY).
没有可用于调用函数的对象。

缺少“static”关键字

如果您只想要一个独特的运动场,还有其他选项: 您可以将Playfield设置为单例,将其转换为命名空间或使用全局函数。 从调用方的角度来看,结果是相同的

旁注: 由于所有这些都使用静态和/或全局变量,因此它本质上不是线程安全的

如果您需要多个Playfield和/或希望安全地使用多线程和/或希望绝对以OOP方式执行此操作,则需要Playfield的实例来调用函数(“this”指针):

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

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

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

如果您不想公开帮助器函数,那么让一个类包含函数集合而不包含任何数据成员是很有用的。
否则,使用名称空间在中收集这些函数会更实际。
例如:

类求解器
{
公众:
void solve_a(标准::矢量数据);
void solve_b(标准::向量数据,int值);
私人:
int helper_a(int a,int b);
}
但是类在使用前需要进行初始化。
使这些函数可用的最简单方法是在类中将它们标记为静态:
static void solve_a(std::vector data);

然后成员函数可以用作:
Solver::求解a(我的向量);

另一种方法是在使用之前初始化类:
解算器;

solver.solve_a(我的向量);

前面没有提到的第三种方法是在使用过程中默认初始化:

Solver().solve_a(my_vector);

谢谢你的回答。在我的程序中,ThreeDCubePlayer是ThreeDCubeGame中的一个实例-这是否意味着我可以在ThreeDCubePlayer中创建一个引用相同二维数组的ThreeDCubePlayer实例?你可以使用ThreeDCubePlayer.GetMapEntry(或this->GetMapEntry)(从内部)。
// .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];
}
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];
};
void main()
{
  // static version 
  char tile11 = Playfield::GetTile( 1, 1 );

  // non-static version
  Playfield myPlayfield;
  char tile12 = myPlayfield.GetTile( 1, 2 );
}
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);
}