非法调用非静态成员函数 (C++)?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1847038/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Illegal call to non-static member function (C++)?
提问by benwad
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. 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?
但是,当我编译它时,我收到警告“错误 C2352:'ThreeDCubeGame::GetMapEntry':非静态成员函数的非法调用”。这与变量的范围有关吗?它可以在不重新设计所有代码的情况下修复吗?
回答by Didier Trosset
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.
没有对象可以用来调用函数。
回答by Arkaitz Jimenez
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
-Create an instance of ThreeDCubeGame and do instance.GetMapEntry(
替代方案:
-使 GetMapEntry 静态:-static inline char GetMapEntry
创建 ThreeDCubeGame 的实例并执行instance.GetMapEntry(
回答by catchmeifyoutry
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).
回答by smocoder
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 设为单例,将其转换为命名空间或使用全局函数。从调用者的角度来看,结果是一样的。
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 );
}
回答by Farway
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);
但是一个类需要在使用前进行初始化。
使这些函数可用的最简单方法是在类中将它们标记为静态:static void solve_a(std::vector<int> data);
然后成员函数可以用作: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);
回答by Nick Lewis
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
甚至是班级的成员吗?
回答by Patrice Bernassola
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()
, - declare the GetMapEntry function as static (add a static before inline and make m_acMapData static too).
- 通过ThreeDCubeGame的实例调用它:
threedcubegameinstance.GetMapEntry()
, - 将 GetMapEntry 函数声明为静态函数(在内联之前添加一个静态函数并使 m_acMapData 也是静态的)。