Статическая переменная-член внутри локального класса в C++?

Я знаю, что мы не можем объявить статическую переменную-член внутри локального класса... но причина этого не ясна.

Так, пожалуйста, кто-нибудь может объяснить это?

Кроме того, почему мы не можем получить доступ к нестатическому определению переменной внутри функции, в которой был определен локальный класс, непосредственно в функциях-членах локального класса?

В приведенном ниже коде:

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 доступна напрямую, в то время как аргумент argc из main не является....

6 ответов

  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;
    }
    Локально объявленный экземпляр класса теперь будет существовать за пределами срока службы локальных переменных функции.

Два вопроса связаны между собой. Я считаю, что ответ не ясен для вас, потому что static Ключевое слово в C++ имеет перегруженные значения.

Когда вы определяете статическую переменную внутри функции, вы действительно указываете компилятору инициализировать ее только при первом вызове (чтобы вы могли использовать значение для нескольких вызовов). Это не совсем то же самое в случае статической переменной области файла или области класса.

Имея это в виду, может не иметь смысла определять статическую переменную внутри локального класса, который, в свою очередь, определяется внутри функции.

Что касается вашего второго вопроса, локальный класс на самом деле может получить доступ к статическим переменным, определенным в его функции включения. Например, приведенный ниже код должен компилироваться в совместимый со стандартами компилятор.


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

  local l;
  /* ... */
}

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

Локальные классы не имеют полного доступа к своей среде (спасибо Ричарду)... вы должны использовать, например, ссылки или указатели, чтобы обойти это:

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

Еще одна причина, по которой вы не можете исследовать переменные стека во вложенной области видимости, заключается в том, что функция в локальном классе не обязательно вызывается непосредственно из включающей функции.

В приведенном ниже примере жизнь будет проще, если hello() были единственной функцией в классе: найти переменную stackValue, hello() просто нужно заглянуть в кадр стека его вызывающего. Но здесь я представил 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;
}

Я думаю, что причина в том, что локальные классы не могут иметь статические члены (или функции, определенные вне класса), больше по синтаксическим, чем по семантическим причинам. Статические члены могут быть реализованы так же, как в нелокальных классах: у статического элемента будет время жизни, начинающееся при первом вызове функции, точно так же, как статические переменные, объявленные внутри функции. Компилятор должен убедиться, что статические члены были инициализированы при создании первого экземпляра класса.

Представьте себе проблему с искажением имен теперь, когда подпись включающей функции становится частью имени.;-)

Причина, по которой вы не можете получить доступ к локальным переменным или параметрам функции в локальном классе, заключается в том, что это усложнит код, необходимый для реализации класса, с небольшим выигрышем. Нестатические члены класса обычно доступны через указатель this или указатель на конкретный экземпляр. Для доступа к переменным и параметрам, локальным для включающей функции, потребуется некоторый механизм, чтобы сделать их доступными. Этот механизм может быть довольно тривиальным, если функции были встроены, но что происходит, когда они нет?

Статические переменные инициализируются при запуске программы. Локальные классы загружаются при вызове метода. И выгружается, когда заканчивается вызов метода.

Согласно Википедии

В компьютерном программировании статическая переменная - это переменная, которая была назначена статически - время жизни которой распространяется на весь прогон программы.

Это отличается от загрузки и выгрузки локальных классов, имеющих объявленные статические переменные

Другие вопросы по тегам