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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 17:05:08  来源:igfitidea点击:

C++ static member functions and variables

c++

提问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 mainfor 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 Environmentand 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

staticmembers are those that using them require no instantiation, so they don't have this, since thisrequire 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 staticfunction. 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 staticwhile it require this.

如您所见,您不能在函数内调用实例函数或使用实例成员static。因此,如果一个函数的操作不依赖于实例,那么它应该是静态的,并且如果您需要在您的函数中执行一个 require 的操作this,您必须考虑为什么我static在它需要的时候调用这个函数this

A member variable is staticif it should shared between all instances of a classand it does not belong to any specific classinstance, 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::displayuses the variables numOfRobotsand robots, which both live in a particular instance of the Environmentclass. Either make displaynon-static (why do you want it to be static?) or make the robots static members of Environmenttoo.

静态成员函数是可以在没有那种实际对象的情况下调用的函数。但是,您的函数Environment::display使用变量numOfRobotsand robots,它们都位于类的特定实例中Environment。要么使display非静态(为什么要使其成为静态?),要么使机器人也成为静态成员Environment

In your case, I don't see a reason for making displayor processKeySpecialUpstatic, 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.

在您的情况下,我没有看到制作displayor的原因processKeySpecialUpstatic,因此只需将它们设为普通成员函数即可。如果您想知道什么时候应该使用成员函数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.

静态方法不能访问实例变量。如果要访问实例变量,请从方法中删除静态。如果这些值在所有机器人实例中都相同,则使它们成为静态变量,并且该方法可以保持静态。