8.5.9 Видимость имен членов
Члены класса, описанные с ключевым словом class, являюся закрытыми, то есть, их имена могут использоваться только функциями членами (#8.5.2) и друзьями (см. #8.5.10), если они не стоят после метки «public:». В этом случае они являются открытыми. Открытый член может использоваться любой функцией. Struct является классом, все члены которого общие, см. #8.5.12.
Если производный класс описан как struct или если перед именем базового класса в описании производного класса стоит ключевое слово public, то общие члены базового класса являюся общими для производного класа; в остальных случаях они яляются закрытыми. Открытый член mem закрытого базового класса base может быть описан как общий для производного класса с помощью опиисания вида
typedef-имя :: идентификатор ;
в котором typedef-имя обозначает базовый класс, а идетификатор есть имя члена базового класса. Такое описание должно стоять в открытой части производного класса. Рассморим
class base (* int a; public: int b, c; int bf(); *);
class derived : base (* int d; public: base::c; int e; int df(); *);
int ef(derived amp;);
Внешняя функция ef может использовать только имена c, e и df. Являясь членом производного derived, функция df может использовать имена b, c, bf, d, e и df, но не a. Являясь члном базового base, функция bf может использовать члены a, b, c и bf.
8.5.10 Друзья
Друг класса – это функция не-член, которая может исползовать имена закрытых членов. Друг не принадлежит области вдимости класса и не вызывается с помощью синтаксиса выбора члена (если он не является членом другого класса). Следующий пример иллюстрирует различия между членами и друзьями:
class private (* int a; friend void friend_set(private*, int); public: void member_set(int); *);
void friend_set (private* p, int i) (* p-»a = i; *)
void private::member_set (int i) (* a = i; *)
private obj; friend_set ( amp;obj,10); obj.member_set (10);
Если описание friend отностися к перегруженному имени или операции, то другом становится только функция, задаваемая типами параметров. Член класса cl1 может быть другом класса cl2. Например:
class cl2 (* friend char* cl1::foo(int); // ... *);
Все функции класса cl1 могут быть сделаны друзьями класа cl2 с помощью одного описания
class cl2 (* friend class cl1 ; // ... *);
Функция член, определенная (#10) в описании класса, яляется inline.
8.5.11 Функция операция
Большинство операций могут быть перегружены с тем, чтобы они могли получать в качестве операндов объекты класса.
имя_функции_операции: operator операция
операция: одна из new delete + – * / % ^ amp; ! ~ ! = « » += -= *= /= %= ^= amp;= != «„ “» «„= “»= == != «= »= amp; amp; !! ++ – () []
Последние две операции – это вызов функции и индексирвание. Функция операция (за исключением operator new и operator delete; см. #7.2) должна быть или функцией членом, или получать по меньшей мере один классовый параметр. См. также #7.16.
8.5.12 Структуры
Структура есть класс, все члены которого общие. Это знчит, что
struct s (* ... *); эквивалентно
class s (* public: ... *);
Структура может иметь функции члены (включая конструктры и деструкторы). Базовй класс производной struct является открытым. Это значит, что
struct s : d (* ... *);
эквиволентно
class s : public b (* public: ... *);
8.5.13 Объединения
Объединение можно считать структурой, все объекты члены которой начинаются со смещения 0, и размер которой достаточен для содержания любого из ее объектов членов. В каждый момент времени в объединеии может храниться не больше одного из обектов членов. Объединение может иметь функции члены (включая конструкторы и деструкторы). Из объединения невозможно вывети класс. Объект класса с конструктором или деструктором не может быть членом объединения.
Объединение вида
union (* список_членов *);
называется безымянным объединением; оно определяет неменованный объект. Имена членов безымянного объединения долны отличаться от других имен в области видимости, в которой объединение описано; в этой области видимости они могут ипользоваться непосредственно, без обычного синтаксиса доступа к членам (#8.5). Например:
union (* int a; char* p; *); a = 1; // ... p = «asdf»;
Здесь a и p используются как простые переменные (не-члны), но так как они являются членами объединения, они имеют один и тот же адрес.
8.5.14 Поля бит
Описатель_члена вида
идентификатор opt : константное_выражение
определяет поле; его длина отделяется от имени поля дветочием. Поля упаковываются в машинные целые; они не являются альтернативой слов. Поле , не влезающее в оставшееся в целом место, помещается в следующее слово. Поле не может быть шире слова. На некоторых машинах они размещаются справа налево, а на некоторых слева направо, см. #2.6.
Неименованные поля полезны при заполнении для согласовния внешне предписанных размещений (форматов). В особых слчаях неименованные поля длины 0 задают выравнивание следующго поля по границе слова. Не требуется аппаратной поддержки любых полей, кроме целых. Более того, даже целые поля могут рассматриваться как unsigned. По этим причинам рекомендуется описывать поля как unsigned. К полям не может применяться операция получения адреса amp;, поэтому нет указателей на поля.
Поля не могут быть членами объединения.
8.5.15 Вложенные классы
Класс может быть описан внутри другого класса. Это, онако, лишь соглашение о записи, поскольку внутренний класс принадлежит охватывающей области видимости. Например:
int x;
class enclose (* // охватывающий int x; class inner (* // внутренний int y; void f(int); *); int g(inner*); *);
inner a; void inner::f(int i) (* x = i; *) // присваивает ::x int enclose::g(inner* p) (* return p-»y; *) // ошибка
8.6 Инициализация
Описатель может задавать начальное значение описываемого идентификатора.
инициализатор: = выражение = (* список_инициализаторов , opt *) ( список_выражений ) список_инициализаторов: выражение список_инициализаторов , список_инициализаторов (* список_инициализаторов *)
Все выражения в инициализаторе статической или внешней переменной должны быть константными выражениями, которые опсаны в #12, или выражениями, которые сводятся к адресам ранее описанных переменных, возможно со смещением на константное выражение. Автоматические и регистровые переменные могут инциализироваться любыми выражениями, включащими константы, рнее описанные переменные и функции.
Гарантируется, что неинициализированные статические и внешние переменные получают в качестве начального значения 0. Гарантируется, что неинициализированные автоматические и ргистровые переменные получают в качестве начального значения «пустое место»*.
– * В английском – «garbage», означающее затертое место [памяти], т.е. если переменная целая, то 0, если char, то '\0', если указатель на Т, то (Т*) NULL. (прим. перев.)
Когда инициализатор применяется к скаляру (указатель или объект арифметического типа), он состоит из одного выражения, возможно, заключенного в фигурные скобки. Начальное значение объекта находится из выражения; выполняются те же преобразвания, что и при присваивании.
Заметьте, что поскольку () не является инициализатором, то X a(); является не описанием объекта класса X, а описанием функции, не получающей значений и возвращающей X.