C++ 静态成员函数和变量
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13203999/
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
C++ static member functions and variables
提问by Maxim Neaga
I am learning C++ by making a small robot simulation and I'm having trouble with static member functions inside classes.
我正在通过制作一个小型机器人模拟来学习 C++,但我在类内的静态成员函数方面遇到了麻烦。
I have my Environment class defined like this:
我的 Environment 类定义如下:
class Environment {
private:
int numOfRobots;
int numOfObstacles;
static void display(); // Displays all initialized objects on the screen
public:
Robot *robots;
Obstacle *obstacles;
// constructor
Environment();
static void processKeySpecialUp(int, int, int); // Processes the keyboard events
};
Then in the constructor I initialize the robots and obstacles like this:
然后在构造函数中,我像这样初始化机器人和障碍物:
numOfRobots = 1; // How many robots to draw
numOfObstacles = 1;
robots = new Robot[numOfRobots];
obstacles = new Obstacle[numOfObstacles];
Here is example of static function that uses those variables:
以下是使用这些变量的静态函数示例:
void Environment::display(void) {
// Draw all robots
for (int i=0; i<numOfRobots; i++) {
robots[i].draw();
}
}
When I try to compile, I get error messages like
当我尝试编译时,我收到类似的错误消息
error: invalid use of member ‘Environment::robots' in static member function
I tried making numOfRobots, numOfObstacles, robots and obstacles static, but then I got errors like
我尝试将 numOfRobots、numOfObstacles、robots 和障碍设置为static,但随后出现了类似的错误
error: undefined reference to 'Environment::numOfRobots'
I would greatly appreciate of someone could explain me what I am doing wrong. Thank you!
我将不胜感激有人可以向我解释我做错了什么。谢谢!
回答by Toribio
Static methods can't use non-static variables from its class.
静态方法不能使用其类中的非静态变量。
That's because a static method can be called like Environment::display()
without a class instance, which makes any non-static variable used inside of it, irregular, that is, they don't have a parent object.
那是因为静态方法可以像Environment::display()
没有类实例一样被调用,这使得它内部使用的任何非静态变量都是不规则的,也就是说,它们没有父对象。
You should consider why you are trying to use a static member for this purpose. Basically, one example of how a static method can be used is as such:
您应该考虑为什么要为此目的使用静态成员。基本上,如何使用静态方法的一个示例如下:
class Environment
{
private:
static int maxRobots;
public:
static void setMaxRobots(int max)
{
maxRobots = max;
}
void printMaxRobots();
};
void Environment::printMaxRobots()
{
std::cout << maxRobots;
}
And you would have to initialize on the global scope the variables, like:
并且您必须在全局范围内初始化变量,例如:
int Environment::maxRobots = 0;
Then, inside main
for example, you could use:
然后,main
例如在内部,您可以使用:
Environment::setMaxRobots(5);
Environment *env = new Environment;
env->printMaxRobots();
delete env;
回答by Mark Stevens
There are 2 issues here - the algorithm you're trying to implement and the mechanics of why it won't compile.
这里有两个问题 - 您试图实现的算法以及它无法编译的机制。
Why it doesn't compile.
为什么它不编译。
You're mixing static and instance variables/methods - which is fine. But you can't refer to an instance variable from within a static method. That's the "invalid use" error. If you think about it, it makes sense. There is only one "static void display()" method. So if it tries to refer to the non-static (instance) variable "robots", which one is it referring to? There could be 10 ... or none.
您正在混合静态和实例变量/方法 - 这很好。但是您不能从静态方法中引用实例变量。那是“无效使用”错误。如果你仔细想想,这是有道理的。只有一种“静态无效显示()”方法。因此,如果它试图引用非静态(实例)变量“robots”,它指的是哪一个?可能有 10 个……或没有。
The logic you are trying to implement.
您试图实现的逻辑。
It looks like you want a single Environment class that manages N robots. That's perfectly logical. One common approach is to make Environment a 'singleton' - an instance variable that only allows for a single instance. Then it could allocate as many robots as it want and refer to them freely because there are no static variables/methods.
看起来您想要一个管理 N 个机器人的环境类。这是完全合乎逻辑的。一种常见的方法是使 Environment 成为“单例”——一个仅允许单个实例的实例变量。然后它可以根据需要分配任意数量的机器人并自由引用它们,因为没有静态变量/方法。
Another approach is to just go ahead and make the entire Environment class static. Then keep a (static) list of robots. But I think most people these days would say option #1 is the way to go.
另一种方法是继续使整个 Environment 类保持静态。然后保留一个(静态)机器人列表。但我认为现在大多数人会说选项 #1 是要走的路。
回答by n. 'pronouns' m.
The first error says that you cannot use non-static members in static member functions.
第一个错误表示您不能在静态成员函数中使用非静态成员。
The second one says that you need to definestatic members in addition to declaringthem You must define static member variables outsideof a class, in a source file (not in the header) like this:
第二个说除了声明它们之外,您还需要定义静态成员您必须在类之外定义静态成员变量,在源文件中(而不是在头文件中),如下所示:
int Environment::numOfRobots = 0;
You don't need any static members. To have an absolutely correct and portable GLUT interface, have a file-level object of type Environment
and a file-level (non-member) function declared with C linkage. For convenience, have also a member function named display
.
您不需要任何静态成员。要拥有绝对正确且可移植的 GLUT 接口,请Environment
使用 C 链接声明类型的文件级对象和文件级(非成员)函数。为方便起见,还有一个名为 的成员函数display
。
class Environment
{
public:
void display() { ... }
...
};
static Environment env;
extern "C" void display () { env.display(); }
回答by BigBoss
static
members are those that using them require no instantiation, so they don't have this
, since this
require instantiation:
static
成员是那些使用它们不需要实例化的成员,所以他们没有this
,因为this
需要实例化:
class foo {
public
void test() {
n = 10; // this is actually this->n = 10
}
static void static_test() {
n = 10; // error, since we don't have a this in static function
}
private:
int n;
};
As you see you can't call an instance function or use an instance member inside an static
function. So a function should be static if its operation do not depend on instance and if you require an action in your function that require this
, you must think why I call this function static
while it require this
.
如您所见,您不能在函数内调用实例函数或使用实例成员static
。因此,如果一个函数的操作不依赖于实例,那么它应该是静态的,并且如果您需要在您的函数中执行一个 require 的操作this
,您必须考虑为什么我static
在它需要的时候调用这个函数this
。
A member variable is static
if it should shared between all instances of a class
and it does not belong to any specific class
instance, for example I may want to have a counter of created instances of my class:
成员变量是static
如果它应该在 a 的所有实例之间共享,class
并且它不属于任何特定class
实例,例如我可能想要我的类的创建实例的计数器:
// with_counter.h
class with_counter {
private:
static int counter; // This is just declaration of my variable
public:
with_counter() {++counter;}
~with_counter() {--counter;}
static int alive_instances() {
// this action require no instance, so it can be static
return counter;
}
};
// with_counter.cpp
int with_counter::counter = 0; // instantiate static member and initialize it here
回答by amaurea
A static member function is one that can be called without an actual object of that kind. However, your function Environment::display
uses the variables numOfRobots
and robots
, which both live in a particular instance of the Environment
class. Either make display
non-static (why do you want it to be static?) or make the robots static members of Environment
too.
静态成员函数是可以在没有那种实际对象的情况下调用的函数。但是,您的函数Environment::display
使用变量numOfRobots
and robots
,它们都位于类的特定实例中Environment
。要么使display
非静态(为什么要使其成为静态?),要么使机器人也成为静态成员Environment
。
In your case, I don't see a reason for making display
or processKeySpecialUp
static
, so just make them normal member functions. If you wonder when a member function should be static
, consider if that function would make sense if no objects of that class have been created (i.e. no constructors been called). If the function doesn't make sense in this context, then it shouldn't be static
.
在您的情况下,我没有看到制作display
or的原因processKeySpecialUp
static
,因此只需将它们设为普通成员函数即可。如果您想知道什么时候应该使用成员函数static
,请考虑在没有创建该类的对象(即没有调用构造函数)的情况下该函数是否有意义。如果函数在这种情况下没有意义,那么它不应该是static
.
回答by evanmcdonnal
A static method cannot access instance variables. If you want to access instance variable remove static from the method. If those values can be the same through all robot instances then make them static variables and the method can remain static.
静态方法不能访问实例变量。如果要访问实例变量,请从方法中删除静态。如果这些值在所有机器人实例中都相同,则使它们成为静态变量,并且该方法可以保持静态。