2009-12-04 149 views
4

我正在开发一个基于用户控制在屏幕上的区域之间移动的球的游戏。对于屏幕上的“地图”在文件ThreeDCubeGame.cpp定义:非法调用非静态成员函数(C++)?

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':非法调用非静态成员函数”。这与变量的范围有关吗?它是否可修复而不重新设计所有代码?

回答

4

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

替代方案:
- 制作GetMapEntry静:static inline char GetMapEntry
- 创建ThreeDCubeGame的实例,并做instance.GetMapEntry(

+0

感谢您的回答。 在我的程序中ThreeDCubePlayer是ThreeDCubeGame中的一个实例 - 这是否意味着我可以在ThreeDCubePlayer中创建一个ThreeDCubeGame的实例来引用相同的二维数组? – benwad 2009-12-04 14:06:34

+0

你可以使用ThreeDCubePlayer.GetMapEntry(或this-> GetMapEntry(从内部。 – 2009-12-04 14:08:15

0

您试图调用类方法。那是你的意图吗?或者你的意思是GetMapEntry是一个实例方法?如果它是一个类方法,它需要被标记为静态。如果它是实例方法,则需要使用ThreeDCubeGame的实例调用它。另外,即使是一个班级的成员,也是GetMapEntry

0

错误表明您正在调用GetMapEntry函数作为静态函数,而您已声明它为成员函数。您需要:通过ThreeDCubeGame实例

  • 调用它:threedcubegameinstance.GetMapEntry()
  • 声明GetMapEntry功能为静态(内联之前添加静态,使m_acMapData静太)。
1

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

ThreeDCubeGame map; 
... 
map.GetMapEntry(iMapX, iMapY). 
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 
} 

有没有对象调用与功能。

0

您错过了“静态”关键字。

// .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]; 
} 

还有其他的选择,如果你只需要一个独特的球场: 可以使球场单身,把它变成一个命名空间或使用全局函数。 从调用者的角度来看,结果是一样的。

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

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

调用代码将使用操场这样的:

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

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

而第三种方法,而不是之前所提到的,默认情况下初始化它杜尔ing使用:
Solver().solve_a(my_vector);

相关问题