-->

static member variable inside a local class in c++

2019-04-10 06:56发布

问题:

I know we cannot declare a static member variable inside a local class... but the reason for it is not clear.

So please can anybody explain it?

Also, why can't we access a non-static variable define inside the function, within which the local class has been defined,directly in the local class member functions?

In the code given below:

int main(int argc, char *argv[])
{
    static size_t staticValue = 0;

    class Local
    {
         int d_argc; // non-static data members OK
         public:
         enum // enums OK
         {
             value = 5
         };
         Local(int argc) // constructors and member functions OK
         : // in-class implementation required
          d_argc(argc)
         {
               // global data: accessible
               cout << "Local constructor\n";
               // static function variables: accessible
               staticValue += 5;
         }
         static void hello() // static member functions: OK
         { 
            cout << "hello world\n";
         }
   };
   Local::hello(); // call Local static member
   Local loc(argc); // define object of a local class.
   return 0;
}

Static variable staticValue is directly accessible while on the other hand argc argument from main is not....

回答1:

  1. Static variables/functions of local class: try imagining the syntax, lifetime definition, and name-mangling implementation. I'd give up pretty quickly :)
  2. No access to local variables from local class: because class instance might outlive the function scope. Example:
    class interface; // base class declared somewhere
    
    // creates specific implementations
    interface* factory( int arg ) // arg is a local variable
    {
      struct impl0: interface { /* ... */ }; // local class
      struct impl1: interface { /* ... */ }; // local class
      // ...
    
      switch ( arg )
      {
        case 0: return new impl0;
        case 1: return new impl1;
        // ...
      }
    
      return 0;
    }
    The locally declared class instance would now exist beyond the lifespan of the function local variables.


回答2:

The two questions are related. I believe the answer is not clear to you because the static keyword in C++ has overloaded meanings.

When you define a static variable inside the function, you're really telling the compiler to initialize it only in the first call (so you can use the value across multiple calls). This is not exactly the same of the case of a file-scope or class-scope static variable.

With this in mind it might not make sense to define a static variable inside a local class, which is in turn defined inside a function.

Regarding your second question, a local class actually can access static variables defined in its enclosing function. The code below, for example, should compile in a standards-compliant compiler.


void f()
{
  static int i;
  class local
  {
    int g() { return i; }
  };

  local l;
  /* ... */
}

int main()
{
  f();
  return 0;
}


回答3:

Local classes don't have full access to their enviroment (thanks Richard)... you have to use e.g. references or pointers to work around that:

void f() {
    int i = 0;

    struct local {
        int& i;
        local(int& i) : i(i) {}
        void f() { i = 1; }
    };

    local l(i);
    l.f();
    assert(i==1);
}


回答4:

Another reason why you can't examine stack variables in the enclosing scope is that a function in the local class isn't necessarily called directly from the enclosing function.

In the example below, life would be easy if hello() were the only function in the class: To find the variable stackValue, hello() would simply need to look into its caller's stack frame. But here, I've introduced Local::goodbye(), which may or may not invoke Local::hello. In this case, how would Local::hello() know where to find the enclosing function's stack frame? (We'd need closures to make this work. I love closures, but I can't see that happening in C++.)

int main(int argc, char *argv[])
{
    static size_t staticValue = 0;
    int size_t stackValue = argc;

    class Local
    {
         void hello() 
         { 
            cout << "stackValue is " << stackValue << "\n";
         }
         void goodbye()
         {
            if (stackValue == 42) {
                hello();
            }
            else {
                cout << "Goodbye!\n";
            }
         }
   };
   Local loc;
   loc.hello();
   stackValue = 42;
   loc.goodbye();
   return 0;
}


回答5:

Static variables are initialized when program starts. Local classes are loaded when method is called. And unloaded when method call ends.

According to Wikipedia

In computer programming, a static variable is a variable that has been allocated statically — whose lifetime extends across the entire run of the program.

This is in contrast with loading and unloading of local classes having static variables declared



回答6:

I think the reason that local classes can't have static members (or functions defined outside of the class) is more for syntactical than semantic reasons. Static members could be implemented just as in non-local classes: The static would have the lifetime starting at the first call to a function, just as static variables declared inside a function do. The compiler would have to make sure the static members were initialized when the first instance of the class was created.

Imagine the problem with name mangling now that the enclosing function signature becomes part of the name. ;-)

The reason you can't access local variables or parameters of a function in a local class is that it would complicate the code required to implement the class with little gain. The non-static members of a class are typically accessed via the "this" pointer or pointer to the specific instance. To access variables and parameters local to the enclosing function would require some mechanism to make them accessible. That mechanism might be fairly trivial if the functions were inlined, but what happens when they are not?