C++ static member functions and variables

前端 未结 6 422
北恋
北恋 2021-01-31 11:40

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

相关标签:
6条回答
  • 2021-01-31 12:02

    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
    
    0 讨论(0)
  • 2021-01-31 12:20

    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(); }
    
    0 讨论(0)
  • 2021-01-31 12:22

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

    0 讨论(0)
  • 2021-01-31 12:23

    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.

    0 讨论(0)
  • 2021-01-31 12:28

    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;
    
    0 讨论(0)
  • 2021-01-31 12:29

    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.

    0 讨论(0)
提交回复
热议问题