Б. Страуструп - Язык программирования С++. Специальное издание, 3-изд. Бином. 2004 (1160791), страница 211
Текст из файла (страница 211)
Например: ооЫй (); патеярасеХ( ооЫ и (); //. пате«расе У( ооЫД; ооЫ() (); //- ) Здесь применяются обычные правила видимости и квалификации: ооЫХ; У.//() ( /()'й()'д(); ооЫХ:Х() ( // ошибка; в ХнетЯ УП //правильно Приложение В. Технические подробности ив»»»»» () ( У(); У;П; Х:У()', Х:У:Я; //о»иибка: нет глобальной/О // ошибка: нет глобального У // ои»ибка» в Х нет/О // правильна В.10.3. Пространства имен и классы В.11. Контроль доступа В этом разделе приведено несколько технических примеров, иллюстрирующих конт- роль доступа в дополнение к примерам из 9 15.3. В.11.1.
Доступ к членам Рассмотрим следующий фрагмент кода: е)авв Х( //па умолчанию рг»аа»е т» рп'и; ргв»ее»ег(: »п» ргой риЫ»с »п»риЫ, иоЫгп (); Член Хат имеет неограниченный доступ: иоЫХст () ( рни = 1; //правильно рго» =2; // правильно риЫ 3; // правильно Пространство имен — что именованная область видимости.
Класс — это тип, определенный именованной областью впдимосп», которая описывает, как создаются н ис»»ользуются объекты данного типа. Таким образом, пространство имен — это более простое понятие, нежели класс, и было бы идеально определить класс как пространство имен, включающее несколько дополнительных возможностей. Это почти что так. Пространство имен открыто (9 8.2.9.8), но класс закрыт. Это различие проистекает из того соображения, что классу нужно определять расположение объектов, а это лучше делать в одном месте.
Кроме того, ив(пн-объявления и ив(пд-директивь» применимы к классам только очень ограниченным способом Я 15.2.2). Пространства имен предпочтительнее классов, когда требуется только пнкапсулировать имена. В этом случае аппарат классов для проверки тинов и создания объектов не нужен; достаточно более простой концепции пространств имен. 927 В.11. Контроль доступа Члены производного класса имеют доступ к защищенным и открытым членам Я 15.З): с1азз У риЫ)сХ( и оЫ т де и сей () ооЫ Устйепоей () ( рпи=1; / рго1= 2; / /ошибкои ргт — закрытый член / правильно: рго1 — защищенный член, а тйепвей()— // член производного класса У О правильно: риЫ вЂ” это открытый член рго1= 3 ) Глобальная функция может обращаться только к открытым членам: ооЫ 1(У" р) ( р->рпо = 1; р->рго1=2; р->риЫ = 3; В.11.2.
Доступ к базовым классам Как и члены, базовый класс можно объявить закрытым (ргиа1е), защищенным (рго1ес1егг) или открытым (риЫсс). Рассмотрим пример: //- ); сгазз У1: ри611сХ(); с1азз У2: рго1есгеИХ(); с1азз УЗ. рпоа1еХ (); Поскольку Х является для У1 открытым базовым классом, любая функция может (не- явно) преобразовывать У1* в Х', там, где зто нужно, и обращаться к открытым членам класса Х. Например: со!йЯУ1* ру1, У2' ру2, УЗ* руЗ) ( Х' рх = ру1, // правильно: Х для У1 — это опикрьипый базовый класс ру1 — >а =Т; //правильно рх-ру2; ру2->а = 7; рх = руЗ; //ошибка: Хдля УЗ вЂ” закрытый базовый класс руЗ вЂ” >а = б //ошибка Рассмотрим следующий фрагмент: с(азз Х( ри611а гп1а //ошибка: рпо — закрытый щен // ошибка: ргщ — защищенный член, а/О— //не друг и не член классаХили У //правильнгл риЫ вЂ” это открытый член // ошибки; Х для У2 — защищенный базовьш класс // ошибка Приложение В.
Технические подробности 928 с1азз У2 . рго!ес!ей Х ( ); с! азз 22; риЫш У2 ( иоЫ/(У! ', У2*, У8'); ); Поскольку Х вЂ” зто защищенный базовый класс для У2, только члены и друзья У2, а также члены и друзья производных от У2 классов (например, Х2), могут !неявно) обращаться к открытым и защищенным членам класса Х. Например: иоЫ 22 7" (П*ру1, У2*рд2, УЗ* руЗ) Х' рх = ру1; // правильн ру1->а = 7; //правильн о: Х вЂ” оаасрытый базовыи класса для У1 о // правильно: Х вЂ” защии(енный базовый класс для У2, // а 22 — производный класс от У2 // правильно // ошибка: Х вЂ” защищенный базовый класс для У2, //а 72 — производный класс от У2, но наи не известно, // что ру2 принадлежит к 22 или // как У2;:Х исаользуесася в обьектах, не принадлежащих к 22 // ошибкса 22 не знает, как У2па используется в обьектах, // не принадлежащих к 22 // ошиока: Х вЂ” зпю закрьипый базовьш" класс для УЗ // ошибка рх = !!ь!и; а=7; рх-рд2; ру2 — >а = 7, рх = ру8; рдЗ->а = 7 иоЫ УЗ: /(У1* ру1 ( Х*рх=ру1; ру1->а = 7; У2" руг, УЗ*рдЗ) //правильно: Х вЂ” открытый базовый класс для У1 // правильно // ошибка: Х вЂ” защищенный базовый класс для У2 //осиибка рх = ру2, ру2->а= 7; // правильно: Х вЂ” это закрытый базовый класс для УЗ, // а УЗ::У вЂ” член класса УЗ // правильно рх = руЗ; рд8 — >а=7; В.11.3.
Доступ из членов-классов Члены класса-члена не имеют особого доступа к членам внешнего класса. Аналогично, члены внешнего класса не имеют особого доступа к членам вложенного класса; нужно соблюдать обычные правила доступа Я (0.2.2). Нацрпмер: с1азз Ои!ег ( // внешний !урес1е/!а! Т; т!0 рибйс !и!!2; И наконец рассмотрим; с1азз УЗ: рпиа!еХ( ио!й/(У1; У2', УЗ*); ]; П ос кольку Хя ел яется для УЗ закрытым базовым классом, преобразовывать (неявно) УЗ* в Х' могут только члены и друзья УЗ; они также могут обращаться к открытым и защищенным членам классаХ. Например: 929 В.
11. Контроль доступа зга1!с !л1з; с1аее 1ппег( // внутренний. т1х; ту; риЫ!а оо!дЯОи1ег* р, !п1 в); //ошибка; Ои!егхТ вЂ” закрьппмй !л1 у (1ппег' р) оо!Й Ои1еп:1ппегЯОигег" р, т1 о) ( //ошибка: Ои!ег:з' — закрытой О правильно; Ошегп!2 — откритый (л1 Оигегзу (1ппегл р) ( р — ч/ (1п!з, 2), ге1игп р — >х; //правильно: !плеск/Π— открьипий // ошибка; !ппеп:х — зокритый с1азз !плес; ,/г!епс( с!азз 1ппег; предварительное объявление класса члена // разре!иаел! доступ к Ои!егп!ппег с!азз 1лпег ( 1л! х, ту; риЫьс оо1гЦ(Ои1ее' р, !п1 о); // правильно: !олег — друг оо!с1 Ои1ег:вплел:/(Ои1ег' р, гл! о) ( ,о и=о; // праоильно: !ппег — друг В.11.4. Дру ба Дружба не наследуется и не транзитивна. Например: с!лев А ( /г!епс( с!аев В, !л1а; с!азз В ( зг(епд с1аез С; Однако часто полезно позволить классу-члену обращаться к его внешнему классу.
Этого можно добиться, сделав член другом (/г!ела), Например: с!авв Ои1ег ( 1урейе/!л1 Т; !л1!'; иЬВ: Приложение сз. Технические подробности 930 //ошиоки: С вЂ” недруг классаЛ, неслютря нато, // что приходится другом другу класса Л с1акв.Р. РиЫ(с В ( поЫ/(А' р) ( // ошибка: 11 — не друг класса Л, неслотря на то, // что является прошзводньм~ от друга класса Л р->ич-;"; ) ); В.12. Указатели на члены данных Естественно, понятие указателя на член Я 15.51 применяется к членам данных и к функциям-членам с аргументом и типом возвращаемого значения. Например: тгисГС( сопзГ сИаг' оа1; спет'; ооЫрмп1((пг х) ( сонг оа! х «'Гр', ) ооЫ/1 (1пе); (пГ/2 (); С (сопвг сИас' о) ( оа1 = о; ) гурес(е~ооЫ (С::"РМР1) (1пГ); !уреде~сопв1 сбаг' С: ."РМ; ооЫХ(сс е1, СЬ г2) ( С*р=зг2; РМР1 рХ= с С-.ргте; РМ рт = с,сзоа1; // ошибка: несоответствие типа возвраи(аелтго зноченач //осиибка; несоответствие тини аргутенто О тиибка; несоответствие типа О ошибкаг несоответствие типа Тип указателя на функцию проверяется точно так же, как любой другой тип.
с(азз С( оо(а /(А* р) ( р — >а-н-; гс1 гпс(1); ( 1.*р/) (2); г1.'рт = "по1"; р->'рт = "по2"; г2,рс(пг (8); (р-"Ф (4); р/= 1,С:/1; р/= бС:./2; рт =асс(; рт=рХ // укизатель на Узункцию- член клисса С 1/ с с(ели ч иргументом // указатель ни член динних класса С // типа саас' 931 В.13. Шаблоны В.13. Шаблоны Шаблон класса описывает, как сгенерировать класс по заданному подходящему набору аргументов шаблона. Аналогично, шаблон функции описывает, как сгенерировать функцию по соответствующему набору аргументов шаблона.
Таким образом, шаблоны можно использовать для генерирования типов и исполнимого кода. Вместе с такой выразительной мощью воаникает некоторая сложность. Большая ее часть относится к разнообразию контекстов определения и использования шаблонов. В.13.1. Статические члены 11(аб.лон класса может иметь статические (к1а1!с) члены. Каждый класс, сгенерированный по пваблону, имеет собственную копию статических членов.
Статические члены должны определяться отдельно и могут быть спепиализнрованы. Например: 1етр!а1е<с!авв Т с!аквХ( 0- в1аис Тс!е/ оа1; вга1!с Т'пет Х(Та= с!е/ оа!1 1' 1етр!а1е<с!авв Т ТХ<Т<х(е~ оа! (О, Я; 1етр!асс<с!акв Т Т<Х<Тьгпеш Х(Та((/' ... */) 1етр!а1е<ь !п1Х<1пвьз1е/ оа!<1пвь = О; 1етр!а1е< !п1Х<1пГ спет Х<1п1> (1пгй(/*... */] Если вы хотите сделать объект илн функцию общими для всех членов любого сгенерированного по шаблону класса, вы можете поместить их в нешаблонньпй базовый класс. Например; к1гис1 В ( втаис В* п!1, // должен исп альков атьгл кок общий нулввой Око за тель // во всех классах, производнь<х оп~ В 1етр!а1е с!акв Т с!акяХ.ри(в!!сВ ( //...
В' ВспИ = О; В.13.2. Друзья Как и другие классы, шаблоны классов могут иметь друзей. Рассмотрим примеры Ма1г!х и Ъес1ог из 5 11.5. Обычно как Ма1г(х, так и Ъгес1ог будут шаблонами: 1етр!а1е<с!акк Ть с!акв Ма1г!х; 1етр1а1е<с1акк Ть с!авв !хесгог ( Т и(41 риЬ!!с. /Пепд 7ес!ос о реса 1оьл <ь (со пв1 Ма 1гск< Тьй, со а я! Уес1огй~; 932 Приложение В.