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

时间:2009-12-04 13:45:14

标签: c++ scope

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

char m_acMapData[MAP_WIDTH][MAP_HEIGHT];

ThreeDCubeGame.cpp处理大部分与地图有关的事情,但播放器(和键盘输入)由ThreeDCubePlayer.cpp控制。当玩家进入新的地图单元格时,游戏必须检查该单元格的内容并采取相应的行动。我正在尝试使用ThreeDCubeGame.cpp中的这个函数:

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

因此,为了检查是否允许玩家进入地图单元格,我使用来自ThreeDCubePlayer.cpp的函数调用:

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

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

7 个答案:

答案 0 :(得分:10)

class A {
  int i;
public:
  A(): i(0) {}
  int get() const { return i; }
};

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

无法使用。

调用该函数

答案 1 :(得分:5)

GetMapEntry不是static所以如果没有ThreeDCubeGame类型的对象,就无法调用它。

替代品:
 -Make GetMapEntry static:static inline char GetMapEntry
  - 创建ThreeDCubeGame的实例并执行instance.GetMapEntry(

答案 2 :(得分:1)

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

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

答案 3 :(得分:0)

您正在尝试调用类方法。这是你想要的吗?或者你的意思是GetMapEntry是一个实例方法吗?如果它是类方法,则需要将其标记为静态。如果它是实例方法,则需要使用ThreeDCubeGame实例调用它。此外,GetMapEntry甚至是班级成员吗?

答案 4 :(得分:0)

错误表明您将GetMapEntry函数称为静态函数,而您已将其声明为成员函数。你需要:

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

答案 5 :(得分:0)

您错过了“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];
}

如果您只想要一个独特的游戏区域,还有其他选择: 您可以将Playfield设为单例,将其转换为命名空间或使用全局函数。 从呼叫者的角度来看,结果是一样的。

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

如果您需要多个游戏区域和/或想要以多线程安全玩游戏和/或想要以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];
};

调用代码将使用Playfield,如下所示:

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

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

答案 6 :(得分:0)

如果您不希望公开辅助函数,那么让一个包含函数集合的类(没有任何数据成员)会很有用。
否则,使用命名空间来收集这些函数会更实际 示例:

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

但是课程需要在使用前进行初始化 使这些函数可用的最简单方法是在类中将它们标记为静态:
static void solve_a(std::vector<int> data);
然后成员函数可以用作:
Solver::solve_a(my_vector);

另一种方法是在使用之前初始化类:
Solver solver;
solver.solve_a(my_vector);

以前未提及的第三种方法默认在使用期间初始化它:
Solver().solve_a(my_vector);