简体   繁体   中英

C++ static member functions and variables

I am learning C++ by making a small robot simulation and I'm having trouble with static member functions inside classes.

I have my Environment class defined like this:

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

error: undefined reference to 'Environment::numOfRobots'

I would greatly appreciate of someone could explain me what I am doing wrong. Thank you!

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.

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:

Environment::setMaxRobots(5);

Environment *env = new Environment;
env->printMaxRobots();
delete env;

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.

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.

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.

static members are those that using them require no instantiation, so they don't have this , since this require instantiation:

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 .

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:

// 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

The first error says that you cannot use non-static members in static member functions.

The second one says that you need to define static members in addition to declaring them You must define static member variables outside of 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 .

class Environment 
{
 public:
   void display() { ... }
   ... 
};

static Environment env;
extern "C" void display () { env.display(); }

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.

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 (ie no constructors been called). If the function doesn't make sense in this context, then it shouldn't be static .

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.

如果要访问静态成员函数中的成员变量,只需创建成员变量的静态指针并在函数中使用它!!!!!!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM