То, как я интерпретирую Стандарт, пример кода хорошо сформирован.(И да, объявления friend
сильно отличаются от того, что цитирует @Steve Townsend.)
11.2p1: если класс объявлен базовым для другого класса с использованием private
спецификатор доступа, члены public
и protected
базового класса доступны как private
члены производного класса.
11.2p4: член m доступенпри названии в классе N , если
- m в качестве члена N является общедоступным или
- m как член N является закрытым, и ссылка встречается у члена или друга класса N или
- m как член N защищен, и ссылка встречается у члена или друга класса N или у члена или друга класса P получено из N , где m как член P является частным или защищенным, или
- существует базакласс B N , который доступен в исходной точке, и m доступен, когда назван в классе B .
11.4p1: другкласса - это функция или класс, который не является членом класса, но ему разрешено использовать закрытые и защищенные имена членов из класса.
В пункте 11 нет операторов (Доступ к члену)контроль), что подразумевает, что у друга в классе меньше прав доступа, чем у класса, который подружился с ним.Обратите внимание, что «доступный» определяется только в контексте определенного класса.Хотя мы иногда говорим о том, что член или базовый класс являются «доступными» или «недоступными» в целом, было бы точнее говорить о том, «доступен ли он во всех контекстах» или «доступен во всех классах» (как в случаекогда используется только public
).
Теперь для частей, которые описывают проверки контроля доступа в автоматически определенных методах.
12.1p7: неявно объявленный конструктор по умолчанию длякласс неявно определяется , когда он используется для создания объекта своего типа (1.8).Неявно определенный конструктор по умолчанию выполняет набор инициализаций класса, которые будут выполняться пользовательским конструктором по умолчанию для этого класса с пустым mem-initializer-list (12.6.2) и пустымФункциональное тело.Если этот пользовательский конструктор по умолчанию будет некорректно сформирован, программа будет некорректно сформирована.
12.6.2p6: Все подобъекты, представляющие виртуальные базовые классы, инициализируются конструктором самого производного класса (1.8.).Если конструктор самого производного класса не указывает mem-initializer для виртуального базового класса V
, то вызывается конструктор по умолчанию V
для инициализации подобъекта виртуального базового класса.Если V
не имеет доступного конструктора по умолчанию, инициализация некорректна.
12.4p5: неявно объявленный деструктор неявно определен , когда он используется для уничтожения объектасвоего класса (3.7).Программа плохо сформирована, если класс, для которого неявно определен деструктор, имеет:
- нестатический член данных типа класса (или его массив) с недоступным деструктором, или
- базовый класс с недоступным деструктором.
12.8p7: неявно объявленный конструктор копирования неявно определен , если он используется для инициализацииобъект его типа класса из копии объекта его типа класса или типа класса, полученного из его типа класса.[Примечание: конструктор копирования неявно определяется, даже если реализация исключает его использование (12.2).] Программа плохо сформирована, если класс, для которого неявно определен конструктор копирования, имеет:
- нестатический член данных типа класса (или его массив) с недоступным или неоднозначным конструктором копирования, или
- базовый класс с недоступным или неоднозначным конструктором копирования.
12.8p12: Программа плохо сформирована, если класс, для которого неявно определен оператор присваивания копии:
- нестатический элемент данных типа
const
или
- нестатический элемент данных ссылочного типа или
- нестатический член данных типа класса (или его массив) с оператором недоступного копирования или
- базовый класс с недоступным оператором присваивания копии.
Все эти требования, упоминающие «недоступный» или «доступный», должны интерпретироваться в контексте некоторого класса, и единственный класс, который имеет смысл, - это тот, для которого функция-член неявно определена.
В исходном примере class A
неявно имеет public
конструктор по умолчанию, деструктор, конструктор копирования и оператор присваивания копии. Согласно 11.2p4, поскольку class C
является другом class A
, все эти члены доступны, когда они названы в классе C
. Поэтому проверки доступа к этим элементам class A
не приводят к неправильному формированию неявных определений конструктора, деструктора, конструктора копирования или оператора копирования по умолчанию class C
.