Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ static member functions and variables

Tags:

c++

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!

like image 684
Maxim Neaga Avatar asked Nov 02 '12 22:11

Maxim Neaga


3 Answers

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;
like image 129
Toribio Avatar answered Oct 23 '22 17:10

Toribio


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.

like image 31
Mark Stevens Avatar answered Oct 23 '22 17:10

Mark Stevens


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
like image 37
BigBoss Avatar answered Oct 23 '22 18:10

BigBoss