C++ static member functions and variables
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
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.
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(); }
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;