c ++中本地类内的静态成员变量?

时间:2010-01-06 12:04:16

标签: c++ static local-class

我知道我们不能在本地类中声明一个静态成员变量... 但其原因尚不清楚。

那么请有人解释一下吗?

另外,为什么我们不能直接在本地类成员函数中访问函数内部的非静态变量(定义本地类)?

在下面给出的代码中:

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;
}

静态变量staticValue可以直接访问,而另一方面来自main的argc参数不是....

6 个答案:

答案 0 :(得分:4)

这两个问题是相关的。我相信你的答案并不清楚,因为C ++中的static关键字意味着重载。

当你在函数中定义一个静态变量时,你真的告诉编译器只在第一次调用时初始化它(所以你可以在多次调用中使用该值)。这与文件范围或类范围静态变量的情况不完全相同。

考虑到这一点,在本地类中定义静态变量可能没有意义,而本地类又在函数内定义。

关于第二个问题,本地类实际上可以访问其封闭函数中定义的静态变量。例如,下面的代码应该在符合标准的编译器中编译。


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

  local l;
  /* ... */
}

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

答案 1 :(得分:4)

  1. 本地类的静态变量/函数:尝试想象语法,生命周期定义和名称修改实现。我很快就放弃了:)
  2. 无法从本地类访问本地变量:因为类实例可能比函数范围更长。例:
    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;
    }
    现在,本地声明的类实例将存在于函数局部变量的生命周期之外。

答案 2 :(得分:3)

本地课程没有完全访问他们的环境(感谢Richard)...你必须使用例如参考或指针解决这个问题:

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);
}

答案 3 :(得分:1)

您无法检查封闭范围中的堆栈变量的另一个原因是本地类中的函数不一定直接从封闭函数调用。

在下面的示例中,如果hello()是类中唯一的函数,生活会很容易:要查找变量stackValuehello()只需查看其调用者的堆栈帧。但是在这里,我已经介绍了Local::goodbye(),它可能会也可能不会调用Local::hello。在这种情况下,Local::hello()如何知道在哪里找到封闭函数的堆栈帧? (我们需要使用闭包来完成这项工作。我喜欢闭包,但我不能在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;
}

答案 4 :(得分:0)

程序启动时初始化静态变量。调用方法时会加载本地类。并在方法调用结束时卸载。

根据维基百科

  

在计算机编程中,静态   变量是一个变量   静态分配 - 其寿命   延伸到整个运行期间   程序

这与加载和卸载具有声明的静态变量

的本地类形成对比

答案 5 :(得分:0)

我认为本地类不能拥有静态成员(或在类之外定义的函数)的原因更多的是语法而非语义原因。静态成员可以像在非本地类中一样实现:静态的生命周期从第一次调用函数开始,就像函数内部声明的静态变量一样。编译器必须确保在创建类的第一个实例时初始化静态成员。

想象一下,由于封闭的函数签名成为名称的一部分,名称损坏的问题。 ; - )

您无法在本地类中访问函数的局部变量或参数的原因是它会使实现该类所需的代码复杂化很少。通常通过“this”指针或指向特定实例的指针来访问类的非静态成员。要访问封闭函数本地的变量和参数,需要一些机制来使它们可访问。如果函数被内联,那么这个机制可能相当简单,但是当它们不是这样时会发生什么?