Язык программирования C++ от Страуструпа

       

Вложенные классы


Описание класса может быть вложенным. Например:

class set {

  struct setmem {

     int mem;

     setmem* next;

     setmem(int m, setmem* n) { mem=m; next=n; }

  };

  setmem* first;

  public:

     set() { first=0; }

     insert(int m) { first = new setmem(m,first); }

     // ...

};



Доступность вложенного класса ограничивается областью видимости лексически объемлющего класса:

setmem m1(1,0);                    // ошибка: setmem не находится

                                   // в глобальной области видимости

Если только описание вложенного класса не является совсем простым, то лучше описывать этот класс отдельно, поскольку вложенные описания могут стать очень запутанными:

class setmem {

  friend class set;                // доступно только для членов set

  int mem;

  setmem* next;

  setmem(int m, setmem* n) { mem=m; next=n; }

  // много других полезных членов

};

class set {

  setmem* first;

  public:

     set() { first=0; }

     insert(int m) { first = new setmem(m,first); }

     // ...

};

Полезное свойство вложенности - это сокращение числа глобальных имен, а недостаток его в том, что оно нарушает свободу использования вложенных типов (см. $$12.3).

Имя класса-члена (вложенного класса) можно использовать вне описания объемлющего его класса так же, как имя любого другого члена:

class X {

  struct M1 { int m; };

  public:

     struct M2 { int m; };

     M1 f(M2);

};

void f()

{ M1 a;                            // ошибка: имя `M1' вне области видимости

  M2 b;    // ошибка: имя `M1' вне области видимости

  X::M1 c; // ошибка: X::M1 частный член

  X::M2 d; // нормально

}

Отметим, что контроль доступа происходит и для имен вложенных классов.

В функции-члене область видимости класса начинается после уточнения X:: и простирается до конца описания функции. Например:

M1 X::f(M2 a)    // ошибка: имя `M1' вне области видимости

{ /* ... */ }

X::M1 X::f(M2 a)  // нормально

{ /* ... */ }

X::M1 X::f(X::M2 a) // нормально, но третье уточнение X:: излишне

{ /* ... */ }



Содержание раздела