Страница 3 из 48 Синтаксис объявления членов класса
Мы продолжаем формальное определение класса. Теперь рассмотрим синтаксис объявления членов класса. СписокЧленов ::= ОбъявлениеЧленаКласса [СписокЧленов] ::= СпецификаторДоступа : [СписокЧленов] ОбъявлениеЧленаКласса ::= [СписокСпецификаторовОбъявления] [СписокОписателейЧленовКласса]; ::= ОбъявлениеФункции ::= ОпределениеФункции [;] ::= КвалифицированноеИмя; СписокОписателейЧленовКласса ::= ОписательЧленаКласса ::= СписокОписателейЧленовКласса, ОписательЧленаКласса ОписательЧленаКласса ::= Описатель [ЧистыйСпецификатор] ::= [Идентификатор] : КонстантноеВыражение ЧистыйСпецификатор ::= = 0 КвалифицированноеИмяКласса ::= ИмяКласса ::= ИмяКласса :: КвалифицированноеИмяКласса СпецификаторДоступа ::= private ::= protected ::= public
Список членов определяет полный набор членов данного класса. В этом списке объявляются все члены класса. Таковыми могут быть данные, функции-члены, ранее объявленные классы, перечисления, битовые поля, дружественные функции и даже имена типов. Некоторые из перечисленных понятий нам уже знакомы, о других речь ещё впереди. Этот список не подлежит модификации. Он формируется за один раз. В соответствии с синтаксическими правилами, членами класса могут быть как определения функций, так и их прототипы. Действительно: ОбъявлениеЧленаКласса ::= [СписокСпецификаторовОбъявления] [СписокОписателейЧленовКласса]; ::= СпецификаторОбъявления ОписательЧленаКласса; ::= СпецификаторТипа Описатель; ::= void Описатель (СписокОбъявленийПараметров); ::= void ff (void);
С другой стороны, ОбъявлениеЧленаКласса ::= ОпределениеФункции [;] ::= Описатель (СписокОбъявленийПараметров) ТелоФункции ::= ff (void) {int iVal = 100;}
В соответствии с синтаксическими правилами, членами класса могут быть как определения функций, так и их прототипы. Действительно: ОбъявлениеЧленаКласса ::= [СписокСпецификаторовОбъявления] [СписокОписателейЧленовКласса]; ::= СпецификаторОбъявления ОписательЧленаКласса; ::= СпецификаторТипа Описатель; ::= void Описатель (СписокОбъявленийПараметров); ::= void ff (void);
С другой стороны, ОбъявлениеЧленаКласса ::= ОпределениеФункции [;] ::= Описатель (СписокОбъявленийПараметров) ТелоФункции ::= ff (void) {int iVal = 100;}
Точка с запятой после определения функции является декоративным элементом. Ни один член класса не может входить в список членов класса дважды. Поэтому определяемая в теле класса функция оказывается без прототипа. Если класс содержит прототип функции в качестве члена класса, функция располагается за пределами класса. Как мы скоро увидим, всё разнообразие объявлений и определений функций-членов транслятор приводит к единому стандартному виду. Функции-члены могут определяться вне списка членов класса. При определении функции-члена класса за пределами данного класса, в списке членов класса размещается прототип функции-члена. А при определении функции-члена используется квалифицированное имя. Квалифицированное имя состоит из последовательности имён классов, разделённых операциями разрешения области видимости. Эта последовательность имён завершается именем определяемой функции. Последовательность имён классов в квалифицированных именах определяется степенью вложенности объявлений классов. Наличие функций-членов делает объявление класса подобным определению (как и любые функции, функции-члены определяются). Как сказано в Справочном руководстве по C++, "Если бы не исторические причины, объявление класса следовало называть определением класса". Данные-члены класса не могут объявляться со спецификаторами auto, extern, register. Ни при каких обстоятельствах не допускается объявление одноименных членов. Имена данных-членов должны также отличаться от имён функций-членов. Использование одноимённых функций, констант и переменных в выражениях в пределах одной области действия имён приводит к неоднозначности. Как известно, имя функции, как и имя константы и переменной, является выражениями. Если допустить объявление одноимённых переменных, констант и функций, то в ряде случаев просто невозмо будет определить, о чём в программе идёт речь. Объявляемые в классе данные-члены, которые являются представителями классов, должны представлять ранее объявленные классы. Транслятор должен знать заранее о структуре подобных данных-членов. Описатель члена класса в объявлении класса не может содержать инициализаторов (это всего лишь объявление). Структура является классом, объявленным с ключевым словом класса struct. Члены такого класса и базовые классы по умолчанию обладают спецификацией доступа public. Назначение спецификаторов доступа будет обсуждаться в разделах, посвящённых управлению доступом. Пока будет достаточно в объявлении класса указать спецификатор public. В этом случае члены класса оказываются доступны (к ним можно будет свободно обращаться) из любого оператора программы. Объединение является классом, объявленным с ключевым словом класса union. Его члены также по умолчанию обладают спецификацией доступа public. В каждый момент исполнения программы объединение включает единственный член класса. В этом его специфика. Именно поэтому не может быть пустого объединения. Позже мы вернёмся к объединениям. Если функция-член определяется вне тела класса, в список членов класса включается прототип функции. Определение функции сопровождается квалифицированным именем, которое указывает транслятору на принадлежность определяемой функции-члена классу. Последняя часть квалифицированного имени (собственно имя функции) должна совпадать с именем прототипа функции-члена, объявленного ранее в классе. Подобно определению данных основных типов, в программе могут быть определены объекты ранее объявленного типа. В ходе определения объекта-представителя класса выделяется память для размещения данных-членов класса. При этом непосредственно в этой области памяти размещаются все данные-члены, за исключением данных, объявленных со спецификатором static (об этом спецификаторе будет сказано ниже). |