статическая переменная-член внутри локального класса в C ++? - PullRequest
4 голосов
/ 06 января 2010

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

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

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

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

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 ]

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

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

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

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

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


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

  local l;
  /* ... */
}

int main()
{
  f();
  return 0;
}
3 голосов
/ 06 января 2010

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

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);
}
1 голос
/ 06 января 2010

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

В приведенном ниже примере жизнь была бы легкой, если бы 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;
}
0 голосов
/ 06 января 2010

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

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

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

0 голосов
/ 06 января 2010

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

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

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

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

...