12 Classes [class]

12.2 Class members [class.mem]

member-specification:
	member-declaration member-specificationopt
	access-specifier : member-specificationopt
member-declaration:
	attribute-specifier-seqopt decl-specifier-seqopt member-declarator-listopt ;
	function-definition
	using-declaration
	static_assert-declaration
	template-declaration
	deduction-guide
	alias-declaration
	empty-declaration
member-declarator-list:
	member-declarator
	member-declarator-list , member-declarator
member-declarator:
	declarator virt-specifier-seqopt pure-specifieropt
	declarator brace-or-equal-initializeropt
	identifieropt attribute-specifier-seqopt : constant-expression
virt-specifier-seq:
	virt-specifier
	virt-specifier-seq virt-specifier
virt-specifier:
	override
	final
pure-specifier:
	= 0

В member-specificationопределении класса объявляется полный набор членов класса; ни один участник не может быть добавлен в другое место. A direct member класса X - это член, X который был впервые объявлен внутри member-specificationкласса X, включая анонимные объекты объединения ([class.union.anon]) и их прямые члены. Члены класса - это члены данных member functions, вложенные типы, перечислители member templates и их специализации. [ Note: Специализацией шаблона статического элемента данных является статический член данных. Специализацией шаблона функции-члена является функция-член. Специализацией шаблона класса-члена является вложенный класс. ]end note

A member-declarationне объявляет новых членов класса, если он

Для любого другого member-declarationкаждый объявленный объект, который не является, unnamed bit-field является членом класса, и каждый такой member-declaration должен либо объявить по крайней мере одно имя члена класса, либо объявить по крайней мере одно безымянное битовое поле.

A data member - нефункциональный член, представленный a member-declarator. A member function - это член, являющийся функцией. Вложенные типы - это классы ([class.name], [class.nest]), enumerations объявленные в классе, и произвольные типы, объявленные как члены с помощью символа typedef declaration или alias-declaration. Перечислители unscoped enumeration определенного в классе являются членами класса.

Член данных или функция - член может быть объявлена static в его member-declaration, в этом случае он является static member (см [class.static]) (а static data member ([class.static.data]) или static member function ([class.static.mfct]) соответственно) класса. Любой другой член данных или функция-член - это non-static member (a non-static data member или non-static member function ([class.mfct.non-static]) соответственно). [ Note: Нестатический член данных не ссылочного типа является подобъектом члена объекта класса ([intro.object]). ]end note

Член не может быть объявлен дважды в группе member-specification, за исключением того, что

  • шаблон вложенного класса или класса-члена может быть объявлен, а затем определен позже, и

  • перечисление можно ввести с помощью, opaque-enum-declarationа затем повторно объявить с помощью enum-specifier.

[ Note: Одно имя может обозначать несколько функций-членов при условии, что их типы существенно различаются (пункт [over]). ]end note

Класс считается полностью определенным типом объекта ([basic.types]) (или полный типом) , при закрытии } из class-specifier. Внутри класса member-specificationкласс считается завершенным в телах функций, аргументах по noexcept-specifiersумолчанию и инициализаторах членов по умолчанию (включая такие вещи во вложенных классах). В противном случае он считается неполным в рамках своего класса member-specification.

В a member-declarator, = следующий за declarator ним интерпретируется как вводящий, pure-specifier если у declarator-idнего есть тип функции, в противном случае он интерпретируется как вводящий brace-or-equal-initializer. [Example:

struct S {
  using T = void();
  T * p = 0;        // OK: brace-or-equal-initializer
  virtual T f = 0;  // OK: pure-specifier
};

end example]

A brace-or-equal-initializerдолжен появляться только в объявлении элемента данных. (Для статических элементов данных см [class.static.data].; Для нестатических элементов данных см. [class.base.init] И [dcl.init.aggr]). A brace-or-equal-initializerдля нестатического члена данных указывает a default member initializer для члена и не должен прямо или косвенно вызывать неявное определение конструктора по умолчанию по умолчанию для включающего класса или спецификации исключения этого конструктора.

Член не может быть объявлен с . В определении класса член не должен объявляться с помощью, если он также не объявлен . extern storage-class-specifier thread_­local storage-class-specifier static

decl-specifier-seqМожет быть опущен только в деклараций конструктор, деструктор и функция преобразования; при объявлении другого типа члена в нем decl-specifier-seq должен содержаться a, type-specifierкоторый не является a cv-qualifier. member-declarator-listМожет быть опущен только после того, как class-specifierили enum-specifierили в friend declaration. A pure-specifierдолжен использоваться только в декларации a, virtual function которая не является friend декларацией.

Необязательный параметр attribute-specifier-seqв a member-declaration относится к каждой из сущностей, объявленных объектом member-declarators; он не должен появляться, если member-declarator-listопущено необязательное .

A virt-specifier-seqдолжен содержать не более одного каждого из них virt-specifier. А virt-specifier-seq должен фигурировать только в декларации а virtual member function.

Нестатические элементы данных не должны иметь неполных типов. В частности, класс C не должен содержать нестатического члена класса C, но он может содержать указатель или ссылку на объект класса C.

[ Note: См. [expr.prim] Ограничения на использование нестатических элементов данных и нестатических функций-членов. ]end note

[ Note: Тип нестатической функции-члена - это обычный тип функции, а тип нестатического члена данных - это обычный тип объекта. Не существует специальных типов функций-членов или типов данных-членов. ]end note

[ Example: Простой пример определения класса:

struct tnode {
  char tword[20];
  int count;
  tnode* left;
  tnode* right;
};

который содержит массив из двадцати символов, целого числа и двух указателей на объекты одного типа. После того, как это определение было дано, декларация

tnode s, *sp;

объявляет s как tnode и sp как указатель на tnode. С помощью этих объявлений sp->count относится к count члену объекта, на который sp указывает; s.left ссылается на left указатель поддерева объекта s; и s.right->tword[0] относится к начальному символу tword члена right поддерева s. ]end example

Нестатические элементы данных класса (не объединенного) с тем же самым access control выделяются так, чтобы более поздние члены имели более высокие адреса в объекте класса. Порядок распределения нестатических членов данных с разными access control не определен. Требования согласования реализации могут привести к тому, что два соседних элемента не будут размещены сразу после друг друга; так что требования к пространству для управления virtual functions и виртуального base classes.

Если T это имя класса, то каждое из следующих имен должно иметь имя, отличное от T:

  • каждый статический член данных класса T;

  • каждая функция-член класса T [ Note: Это ограничение не распространяется на те constructors, у которых нет имен ];end note

  • каждый член класса, T который сам является типом;

  • каждый шаблон члена класса T;

  • каждый перечислитель каждого члена класса, T который является перечислимым типом без области действия; а также

  • каждый член каждого анонимного союза, который является членом класса T.

Кроме того, если класс T объявлен пользователем constructor, каждый нестатический член данных класса T должен иметь имя, отличное от T.

common initial sequence Двух standard-layout struct типов является самой длинной последовательности нестатические элементов данных и битовых полей в порядке декларации, начиная с первого такого лица в каждой из структур, таким образом, что соответствующие лица имеют макет-совместимых типов и либо ни юридическое лицо немного -field или оба являются битовыми полями с одинаковой шириной. [Example:

  struct A { int a; char b; };
  struct B { const int b1; volatile char b2; };
  struct C { int c; unsigned : 0; char b; };
  struct D { int d; char b : 4; };
  struct E { unsigned int e; char b; };

Общая начальная последовательность A и B включает всех членов любого класса. Общая начальная последовательность A and C и of A и D включает в себя первый член в каждом случае. Общая начальная последовательность A и E пуста. ]end example

Два standard-layout struct типа - это layout-compatible classes если их общая начальная последовательность включает все члены и битовые поля обоих классов ([basic.types]).

Два объединения со стандартным макетом совместимы с макетом, если они имеют одинаковое количество нестатических элементов данных и соответствующие нестатические элементы данных (в любом порядке) layout-compatible types.

В объединении стандартного макета с active member типом структуры T1разрешено читать нестатический член m данных другого члена объединения с типом структуры, T2 если он m является частью общей начальной последовательности T1 и T2; поведение такое, как если бы был назначен член-корреспондент T1 . [Example:

struct T1 { int a, b; };
struct T2 { int c; double d; };
union U { T1 t1; T2 t2; };
int f() {
  U u = { { 1, 2 } };   // active member is t1
  return u.t2.c;        // OK, as if u.t1.a were nominated
}

end example] [ Note: Чтение изменчивого объекта через энергонезависимое значение glvalue имеет неопределенное поведение ([dcl.type.cv]). ]end note

Если объект класса стандартного макета имеет какие-либо нестатические элементы данных, его адрес совпадает с адресом его первого нестатического члена данных. В противном случае его адрес совпадает с адресом его первого подобъекта базового класса (если есть). [ Note: Следовательно, внутри объекта структуры стандартного макета может быть безымянное заполнение, но не в его начале, что необходимо для достижения надлежащего выравнивания. ] [ Объект и его первый подобъект взаимопреобразуемы по указателю ( , ). ]end noteNote: [basic.compound] [expr.static.cast]end note

12.2.1 Member functions [class.mfct]

Функция-член может быть defined в своем определении класса, и в этом случае это inline функция-член, или она может быть определена вне определения своего класса, если она уже была объявлена, но не определена в определении своего класса. Определение функции-члена, которое появляется за пределами определения класса, должно появиться в области пространства имен, включающей определение класса. За исключением определений функций-членов, которые появляются вне определения класса, и за исключением явных специализаций функций-членов шаблонов классов и шаблонов функций-членов ([temp.spec]), появляющихся вне определения класса, функция-член не должна повторно объявляться.

Встроенная функция-член (статическая или нестатическая) также может быть определена вне ее определения класса, если ее объявление в определении класса или ее определение вне определения класса объявляет функцию как inline или constexpr. [ Note: Функции-члены класса в области пространства имен имеют связь с этим классом. Функции- local class члены не связаны. Смотрите [basic.link]. ]end note

[ Note: В программе может быть не более одного определения не встроенной функции-члена. В программе может быть несколько inline определений функции-члена. Смотрите [basic.def.odr] и [dcl.inline]. ]end note

Если определение функции-члена лексически находится за пределами определения ее класса, имя функции-члена должно быть уточнено именем ее класса с использованием ​::​ оператора. [ Note: Имя, используемое в определении функции-члена (то есть при parameter-declaration-clauseвключении default arguments или в теле функции-члена) ищется, как описано в [basic.lookup]. ] [end noteExample:

struct X {
  typedef int T;
  static T count;
  void f(T);
};
void X::f(T t = count) { }

Функция-член f класса X определяется в глобальной области видимости; обозначение X​::​f указывает, что функция f является членом класса X и находится в области действия класса X. В определении функции тип параметра T относится к члену typedef, T объявленному в классе, X а аргумент по умолчанию count относится к статическому члену данных, count объявленному в классе X. ]end example

[ Локальные переменный или локальный типа в функции члена всегда относится к той же сущности, или нет функции члена . ]Note: static inlineend note

В объявлениях могут упоминаться ранее объявленные функции-члены friend .

Функции-члены локального класса должны быть определены встроенными в определение их класса, если они вообще определены.

[ Note: Функция-член может быть объявлена ​​(но не определена) с использованием typedef для типа функции. Результирующая функция-член имеет точно такой же тип, как если бы декларатор функции был указан явно, см [dcl.fct]. Например,

typedef void fv();
typedef void fvc() const;
struct S {
  fv memfunc1;      // equivalent to: void memfunc1();
  void memfunc2();
  fvc memfunc3;     // equivalent to: void memfunc3() const;
};
fv  S::* pmfv1 = &S::memfunc1;
fv  S::* pmfv2 = &S::memfunc2;
fvc S::* pmfv3 = &S::memfunc3;

Также см [temp.arg]. ]end note

12.2.2 Non-static member functions [class.mfct.non-static]

Нестатическая функция-член может быть вызвана для объекта своего типа класса или для объекта класса derived из его типа класса с использованием class member access синтаксиса ([over.match.call]). Нестатическая функция-член также может быть вызвана напрямую с использованием синтаксиса вызова функции ([expr.call], [over.match.call]) из тела функции-члена своего класса или класса, производного от этого класса.

Если нестатическая функция-член класса X вызывается для объекта, не относящегося к типу Xили производному от него X, поведение не определено.

Когда объект, id-expressionкоторый не является частью class member access синтаксиса и не используется для формирования указателя на member ([expr.unary.op]), используется в члене класса X в контексте, где this может использоваться, если name lookup разрешает имя в id-expressionнестатическом члене, не являющемся типом некоторого класса C, и если либо id-expressionпотенциально оценивается, либо C является X базовым классом X, то id-expressionпреобразуется в class member access выражение, использующее (*this) в postfix-expression качестве слева от . оператора. [ Note: Если C не X является базовым классом или Xявляется некорректным выражением доступа к члену класса. ] Аналогично во время поиска имени, когда используемый в определении функции-члена для класса разрешается в статический член, перечислитель или вложенный тип класса или базового класса , преобразуется в, в котором имена класса функции-члена. Эти преобразования не применяются в контексте определения шаблона ( ). [end noteunqualified-id X X Xunqualified-idqualified-idnested-name-specifier[temp.dep.type]Example:

struct tnode {
  char tword[20];
  int count;
  tnode* left;
  tnode* right;
  void set(const char*, tnode* l, tnode* r);
};

void tnode::set(const char* w, tnode* l, tnode* r) {
  count = strlen(w)+1;
  if (sizeof(tword)<=count)
      perror("tnode string too long");
  strcpy(tword,w);
  left = l;
  right = r;
}

void f(tnode n1, tnode n2) {
  n1.set("abc",&n2,0);
  n2.set("def",0,0);
}

В теле функции члена tnode​::​set, имена членов tword, count, leftи right обратиться к членам объекта , для которого эта функция вызывается. Таким образом, в вызове n1.set("abc",&n2,0), tword относится к n1.tword, а в вызове n2.set("def",0,0), он относится к n2.tword. Функции strlen, perrorи strcpy не являются членами класса tnode и должны быть объявлены в другом месте. ]110 end example

Функция - член нестатический может быть объявлена const, volatileили const volatile. Это cv-qualifiers влияет на тип файла this pointer. Они также влияют function type на функцию-член; функция - член объявлена const является const функция, функция - член объявлена volatile является volatile функцией членом и функция объявлена членом const volatile является const volatile функцией - членом. [Example:

struct X {
  void g() const;
  void h() const volatile;
};

X​::​g является const функцией членом и X​::​h является const volatile функцией - членом. ]end example

Нестатическая функция-член может быть объявлена ​​с помощью ref-qualifier([dcl.fct]); см [over.match.funcs].

Нестатическая функция-член может быть объявлена virtual ([class.virtual]) или pure virtual ([class.abstract]).

См., Например, <cstring> ([c.strings]).

12.2.2.1 The this pointer [class.this]

В теле нестатического member functionключевого слова ключевое слово this представляет собой выражение prvalue, значение которого является адресом объекта, для которого вызывается функция. Типа this в функции - члене класса X есть X*. Если функция-член объявлена const, типом this является const X*, если функция-член объявлена volatile, типом this является volatile X*, а если функция-член объявлена const volatile, типом this является const volatile X*. [ Note: Таким образом, в const функции-члене доступ к объекту, для которого вызывается функция, осуществляется через const путь доступа. ] [ end noteExample:

struct s {
  int a;
  int f() const;
  int g() { return a++; }
  int h() const { return a++; } // error
};

int s::f() const { return a; }

В a++ теле s​::​h неправильно сформирован, потому что он пытается изменить (часть) объекта, для которого s​::​h() вызывается. Это недопустимо в const функции-члене, потому что this это указатель на const; то есть *this имеет const тип. ]end example

Аналогичным образом volatile семантика применяется в volatile функциях-членах при доступе к объекту и его нестатическим элементам данных.

Функция-член с квалификацией cv может быть вызвана object-expression только в том случае, если объект-выражение имеет квалификацию cv или менее квалификацию cv, чем функция-член. [Example:

void k(s& x, const s& y) {
  x.f();
  x.g();
  y.f();
  y.g();                        // error
}

Вызов y.g() плохо сформирован, потому что y является const и s​::​g() являетсяconst функцией, не являющейся членом, то s​::​g() есть менее квалифицированной, чем объект-выражение y. ]end example

Constructors и destructors не объявляются const, volatile или const volatile. [ Note: Тем не менее, эти функции могут быть вызваны для создания и уничтожения объектов с Cv квалифицированных типов см [class.ctor] и [class.dtor]. ]end note

12.2.3 Static members [class.static]

На статический член s класса X можно ссылаться с помощью qualified-idвыражения X​::​s; нет необходимости использовать class member access синтаксис для ссылки на статический член. На статический член можно ссылаться с использованием синтаксиса доступа к члену класса, и в этом случае вычисляется выражение объекта. [Example:

struct process {
  static void reschedule();
};
process& g();

void f() {
  process::reschedule();        // OK: no object necessary
  g().reschedule();             // g() is called
}

end example]

На статический член можно ссылаться непосредственно в области его класса или в области действия класса derived из своего класса; В этом случае статический член упоминаются как если qualified-idиспользовалось выражение, с nested-name-specifierиз qualified-idимен в области видимости класса , из которого ссылается статический член. [Example:

int g();
struct X {
  static int g();
};
struct Y : X {
  static int i;
};
int Y::i = g();                 // equivalent to Y​::​g();

end example]

Если unqualified-idиспользуется в определении статического члена, следующего за членом declarator-id, и name lookup обнаруживается, что это unqualified-idотносится к статическому члену, перечислителю или вложенному типу класса члена (или базового класса класса члена), то unqualified-idпреобразуется в qualified-idвыражение , в котором nested-name-specifierимена класс сферы применения , из которого ссылается элемент. [ Note: См. [expr.prim] Ограничения на использование нестатических элементов данных и нестатических функций-членов. ]end note

Статические члены подчиняются обычному классу member access rules. При использовании в объявлении члена класса static спецификатор должен использоваться только в объявлениях члена, которые появляются внутри member-specificationопределения класса. [ Note: Его нельзя указывать в объявлениях членов, которые появляются в области пространства имен. ]end note

12.2.3.1 Static member functions [class.static.mfct]

[ Note: Правила, описанные в [class.mfct] разделе, применяются к статическим функциям-членам. ]end note

[ Note: Статическая функция-член не имеет this pointer. ] Статической функции-члена быть не должно . Не должно быть статической и нестатической функции-члена с одним и тем же именем и одними и теми же типами параметров ( ). Функция - член статический не должен быть объявлен , или .end note virtual[over.load] constvolatile const volatile

12.2.3.2 Static data members [class.static.data]

Статический член данных не является частью подобъектов класса. Если объявлен статический член данных, thread_­local существует одна копия члена на поток. Если статический член данных не объявлен, thread_­local существует одна копия члена данных, совместно используемая всеми объектами класса.

Объявление не встроенного статического члена данных в определении его класса не является определением и может иметь неполный тип, отличный от cv void. Определение статического члена данных, который не определен встроенным в определение класса, должно появиться в области пространства имен, включающей определение класса члена. В определении в области пространства имен имя статического элемента данных должно быть уточнено именем его класса с использованием ​::​ оператора. initializerВыражение в определении члена статических данных в рамках своего класса ([basic.scope.class]). [Example:

class process {
  static process* run_chain;
  static process* running;
};

process* process::running = get_main();
process* process::run_chain = running;

Статический член run_­chain данных класса process определяется в глобальной области видимости; обозначение process​::​run_­chain указывает, что член run_­chain является членом класса process и находится в области действия класса process. В определении статического члена данных initializerвыражение относится к статическому члену running данных класса process. ]end example

[ Note: После определения статического элемента данных он существует, даже если объекты его класса не были созданы. [ Example: В приведенном выше примере run_­chain и running существуют, даже если программа не process создает никаких объектов класса . ] ]end exampleend note

Если энергонезависимый не встроенный const статический член данных имеет целочисленный или перечисляемый тип, его объявление в определении класса может указывать a, brace-or-equal-initializerв котором каждый, initializer-clauseкоторый является, assignment-expression является постоянным выражением ([expr.const]). Этот член по-прежнему должен быть определен в области пространства имен, если он находится odr-used в программе, а определение области пространства имен не должно содержать initializer. Встроенный статический член данных может быть определен в определении класса и может указывать brace-or-equal-initializer. Если член объявлен со constexpr спецификатором, он может быть повторно объявлен в области пространства имен без инициализатора (это использование не рекомендуется; см. [depr.static_constexpr]). Объявления других статических элементов данных не должны указывать a brace-or-equal-initializer.

[ Note: В программе должно быть ровно одно определение статического элемента данных odr-used ; Диагностика не требуется. ] Безымянные классы и классы, прямо или косвенно содержащиеся в безымянных классах, не должны содержать статических элементов данных.end note

[ Note: Статические элементы данных класса в области пространства имен имеют значение linkage этого класса. A local class не может иметь статических элементов данных. ]end note

Статические элементы данных инициализируются и уничтожены точно так же как нелокальных переменных ([basic.start.static], [basic.start.dynamic], [basic.start.term]).

Статический член данных быть не может mutable.

12.2.4 Bit-fields [class.bit]

А member-declaratorформы

identifieropt  attribute-specifier-seqopt : constant-expression

указывает битовое поле; его длина отделяется от имени битового поля двоеточием. Необязательный параметр attribute-specifier-seqотносится к объявляемой сущности. Атрибут битового поля не является частью типа члена класса. constant-expressionДолжна быть интегральным выражением постоянная с большим значением , чем или равно нуль. Значение выражения интегральной константы может быть больше, чем количество бит в object representation типе битового поля; в таких случаях дополнительные биты используются как биты заполнения и не участвуют в value representation битовом поле. Размещение битовых полей внутри объекта класса определяется реализацией. Выравнивание битовых полей определяется реализацией. Битовые поля упакованы в некоторую адресуемую единицу распределения. [ Note: Битовые поля охватывают единицы распределения на одних машинах, но не на других. Битовые поля назначаются справа налево на одних машинах, слева направо на других. ]end note

Объявление для битового поля, в котором не identifier объявляется unnamed bit-field. Безымянные битовые поля не являются членами и не могут быть инициализированы. [ Note: Безымянное битовое поле полезно для заполнения, чтобы соответствовать внешним макетам. ] В качестве особого случая безымянное битовое поле с нулевой шириной определяет выравнивание следующего битового поля на границе единицы распределения. Только при объявлении безымянного битового поля значение поля может быть равно нулю.end noteconstant-expression

Битовое поле не должно быть статическим членом. Битовое поле должно иметь целочисленный или перечислительный тип ([basic.fundamental]). Значение может успешно быть сохранены в битовое поле любого размера ненулевой. Оператор адресации не должен применяться к битовому полю, поэтому нет указателей на битовые поля. Неконстантная ссылка не должна быть привязана к битовому полю ( ). [ Если инициализатором для ссылки типа является lvalue, которое относится к битовому полю, ссылка привязывается к временному инициализированному объекту для хранения значения битового поля; ссылка не связана напрямую с битовым полем. Смотрите . ] bool & [dcl.init.ref]Note: const T& [dcl.init.ref]end note

Если значение true или false сохраняется в битовом поле bool любого размера (включая однобитовое битовое поле), исходное bool значение и значение битового поля должны сравниваться как равные. Если значение перечислителя хранится в битовом поле того же типа перечисления, а количество битов в битовом поле достаточно велико, чтобы содержать все его значения enumeration type, исходное значение перечислителя и значение битового поля. поле сравнивать равно. [Example:

enum BOOL { FALSE=0, TRUE=1 };
struct A {
  BOOL b:1;
};
A a;
void f() {
  a.b = TRUE;
  if (a.b == TRUE)              // yields true
    { /* ... */ }
}

end example]

12.2.5 Nested class declarations [class.nest]

Класс может быть объявлен внутри другого класса. Класс, объявленный внутри другого, называется nested классом. Имя вложенного класса является локальным для включающего его класса. Вложенный класс находится в области его включающего класса. [ Note: См. [expr.prim] Ограничения на использование нестатических элементов данных и нестатических функций-членов. ]end note

[Example:

int x;
int y;

struct enclose {
  int x;
  static int s;

  struct inner {
    void f(int i) {
      int a = sizeof(x);        // OK: operand of sizeof is an unevaluated operand
      x = i;                    // error: assign to enclose​::​x
      s = i;                    // OK: assign to enclose​::​s
      ::x = i;                  // OK: assign to global x
      y = i;                    // OK: assign to global y
    }
    void g(enclose* p, int i) {
      p->x = i;                 // OK: assign to enclose​::​x
    }
  };
};

inner* p = 0;                   // error: inner not in scope

end example]

Функции-члены и статические элементы данных вложенного класса могут быть определены в области пространства имен, включающей определение их класса. [Example:

struct enclose {
  struct inner {
    static int x;
    void f(int i);
  };
};

int enclose::inner::x = 1;

void enclose::inner::f(int i) { /* ... */ }

end example]

Если класс X определен в области пространства имен, вложенный класс Y может быть объявлен в классе X и позже определен в определении класса X или позже определен в области пространства имен, включающей определение класса X. [Example:

class E {
  class I1;                     // forward declaration of nested class
  class I2;
  class I1 { };                 // definition of nested class
};
class E::I2 { };                // definition of nested class

end example]

Как и функция-член, friend function определенный внутри вложенного класса находится в лексической области видимости этого класса; он подчиняется тем же правилам привязки имен, static member function что и класс этого класса, но не имеет особых прав доступа к членам включающего класса.

12.2.6 Nested type names [class.nested.type]

Имена типов подчиняются точно таким же правилам области видимости, как и другие имена. В частности, имена типов, определенные в определении класса, не могут использоваться вне своего класса без уточнения. [Example:

struct X {
  typedef int I;
  class Y { /* ... */ };
  I a;
};

I b;                            // error
Y c;                            // error
X::Y d;                         // OK
X::I e;                         // OK

end example]