Г. Шилдт - Полный справочник по C++ (1109478), страница 53
Текст из файла (страница 53)
Это позволяет неявно выполнять преобразование типа аргумента в тип класса. Помните, что эта альтернатива относится лишь к конструкторам, имеюшим только один параметр. '~ Статические члены класса Члены класса (как функции, так и переменные) могут быть статическими. Рассмотрим эту тему подробнее. Статические переменные-члены Если перед объявлением переменной-члена поставить ключевое слово в»а»ле, компилятор создаст только один экземпляр этой переменной, который будет использоваться всеми объектами данного класса.
В отличие от обычных переменных- членов, статические переменные-члены не копируются для каждого объекта отдельно. Независимо от количества объектов класса, статическая переменная всегда существует в одном экземпляре. Таким образом, все объекты данного класса используют одну и ту же переменную. Все статические переменные инициализируются нулем еше до создания первого объекта класса. Объявление статической переменной-члена в классе не означает ее определения (иначе ~оворя, память лля нее не выделяется). Чтобы разместить статическую пере- га Глава 12.
Классы и объекты менную в памяти, следует определить ее вне класса, т.е. глобально. Для этого в повторном объявлении статической переменной перед ее именем указывается имя класса, которому она принадлежит, и оператор разрешения области видимости. (Напомним, что объявление класса представляет собой все~о лишь логическую схему, а не физическую сушность.) Чтобы разобраться в механизме использования статических переменных-членов, рассмазрим следуюшую программу- Игпс1ибе <1овегеап> цвъпд пагпеврасе все?? с1авв внагес? ( всасъс хпс а; ъпс Ьг рыб?ъс: чоЫ вес(1пс 1, ъпе б) (а=ъ? Ь=бг) чоъб вно»(); ъпе виагеб".:аг // Определяем переменнуп а.
чоЫ внатег?::виси() соцс « "Это статическая переменная а: " « а; соцс « "~пэто обычная переменная Ь: " « Ь? соие « "1п"г ъпс ыа?п() ( виатес? х уг х.вее(1, 1); // Присваиваем переменной а значение 1 х.виоыО г у.вес(2, 2); // Присваиваем переменной Ь значение 2 у.виоы(); х.впои(); /* Здесь одновременно изменяптся значения переменных-членов объектов х и у, поскольку переменная а используется обоими объектами.
*/ гесцгп О; Результат работы этой программы таков. Это статическая переменная а: 1 Это обычная геременная Ь: 1 Это статическая переменная а: 2 Это обычная переменная Ь: 2 Это статическая переменная а". 1 Это обычная переменная а: 1 Обратите внимание на то. что целочисленная переменная а объявлена как внутри класса внвхе(?, так и вне его. Мы уже указывали, что это необходимо, поскольку объявление переменной а внутри класса внахвб не сопровождается выделением памяти. Часть ((. Язык С++ Огпгрьм версии языке С+-~ не требовали впюричного объявления ствпюческой переменнойчленг, чгпо приводило к серьезным недоразумениям, и через несколько лего от эпюго соглашения опгмзелись. Однако нг преюгюке еще вспречеются старые прогргммьх которые не содержал епюричного определения атигпичвскик переменньмчленов.
В эпюк случаях следуегп внести в прогрэ мну нербксдимые исправления. Статическая переменная-член возникает до создания первого объекта класса. Например, в следующей короткой программе переменная а одновременно является и огкрьпой, и статической. Следовательно, функция ма1п( > имеет к ней прямой доступ. Поскольку переменная а возникает раньше объектов класса аваев, ей можно присвоить значение в самом начале программы. Как показано в программе, при создании объекта и значение переменной а не изменяется. По этой причине оба оператора вывода отображают на экране одно и то же значение — 99.
61пс1цде <хоястеагз> цяхпя памеярасе ятдг с1аяв я(затей рцЫхе: ясасхс хпс аг хпе яиатед::аг // Определение переменкой а. хпт ггахп(! // Инициализация перел соэданиел| объекта. яиятед :а = 99г соцс « "Начальное значение переменной а: " « яиатед::аг соцс « "хп"; яиатед х," соос « "Значение переменной х.а." " « х.аг тесцтп О; ) Обратите внимание на то, что при обрашении к переменной а необходимо указывать имя класса, которолгу она принадлежит, и применять оператор разрешения области видимости. Как правило, чтобы обратиться к статической переменной-члену независимо от объекта, необходимо всегда указывать имя класса, в котором она обьявлена.
Статические переменные-члены позволяют управлять доступом к ресурсам, которые совместно используются всеми абъектакзгз класса. Например, можно создать несколько объектов, записывающих данные на жесткий диск. Однако очевидно, что в каждый конкретный момент времени запись может производить лишь один объект. В таких ситуациях следует объявить статическую переменную, служагцую индикатором. По значению этой переменной можно определить, свободен файл или занят. Каждый из объектов должен анализировать это значение перед началом записи. Рассмотрим пример, иллюстрируюший эту ситуацию Ехпс1цде <хояттеазз> цяьпя пагзеярасе ятдг с1аяв с1 ясасхс хпт теяоцтсег рцЫхе: Глава 12.
Классы и обьекгы 1пс пес тевоигсе(); чо1б 1тее тевоитсе() (геяоитсе = Ос) ): 1пс с1::теяоигае/ // Определяем ресурс. 1пг с1::дее тевоитсе() ( 1й(теяоитсе) теситп О; // Ресурс занят. е1ве ( теяоитсе = 1; теситп 1; // Ресурс предоставлен объекту. ) ) 1пс тата() ( с1 оЫ, оЬ2/ 1б(оЬ1.аее гевоигсе!) ) саит « "Объект оы обладает ресурсом1п"; 1г()оЬ2.сее тевоихсе()) саит « "Объекту оЬ2 доступ запрещено"; аЬ1.бтее теяоитсе(); // Освобождаем ресурс. 1й(оЬ2.пег,теяоитсе()) соис « "Объект оЬ2 может использовать ресурс~и"; геситп О; С помошью сгатической переменной можно также определить количество сушесгвуюших объектов конкретного класса. Рассмотрим пример.
В1пс1ие)е <Роветеаю> ияьпц паюеярасе яей; с1аяя Соипсет ( риЫвс: ясас1с ъпс соиле; Соипгег() ( саида++; ) -Соипсет() ( саиде--г ) ); 1пс Соипеет::саиде; чоъб Й(); гпе та1п(чо1б) ( Соипсет о1; саит « "Сугвествуююне объекты: саит « Соипгет::саида « "1п"; Саипеет а2; саит « "Суыоствуююие объекты: соис « Соипеег:."соиле « "1п"; б(); саит « "Суыествуювв<е объекты: соиг « соипгег,:соиле « " 1п"; Часть П. Язык С++ теситп О; уоЫ т() Соиисет сещр; спит « "Существующие объекты: саит « Соиптет::сопит « "тп"; // После возврата мз функции й О переменная Сещр уничтожается ) Зта программа выводит на экран следующие строки.
Существуюшмс объекты: 1 Существующие объекты: 2 Существуюшме объекты: 3 Существующие объекты: 2 Как видим, статическая переменная-член ооипс увеличивается при каждом создании объекта и уменьшается при каждом уничтожении. Следовательно, с ее помощью можно отследить количество существующих объектов класса соипсет. Статические переменные-члены не заменяют собой глобальные.
Однако глобальные переменные не соответствуют духу объектно-ориентированного программирования, поскольку они нарушают принципы инкапсуляции. Статические функции-члены Функции-члены также могут быть статическими, но на них распространяется несколько ограничений. Они имеют прямой доступ только к другим статическим членам класса.
(Разумеется, глобальные функции и данные также доступны статическим функциям-членам.) Статическая функция-член не имеет указателя сь1в. (Зтот указатель описывается в главе (3.) Одна и та же функция не может одновременно иметь статическую и нестатическую версии. Статические функции не могут быть виртуальными. И в заключение, статические функции нельзя объявлять с помощью ключевых слов попас или то1ас11е. Рассмотрим сле~ка измененную версию программы, предоставляющей один и тот же ресурс разным объектам. Обратите внимание на то, что функцию яес тевоитсе() можно вызывать как независимо от объекта, используя имя класса и оператор разрешения области видимости, так и через объект.
аъпс1ибе <ъовттеащ> ивъпд пащеврасе всб; с1авв с1 ( всасъс бпс тевоитсе; ри)з11с: всасъс ъпс оес тевоитсе(): уо16 ттее тевоитсе(] ( тевоитсе = О; тпс с1::тевоитсе; // определение ресурса. 1пс с1::сес тевоитсе() 11(тевоитсе) тетитп О; // Ресурс занят. е1ве ( Глава 12. Классы и объекты гевошсе = 1; гесигп 1; // ресурс предоставлен данному объекту. ) ьпс таьп() ( с1 оЬ1, оЬ2; /* Функция дее гевоигсе() является статической, поэтому ее можно вызывать независимо от объекта. */ 1г(с1:мдес тевоитсе(]) соис « "Объект оь1 обладает ресурсом1п"; ье()'с1::пес тевоитсе(!] соис « "Объекту оь2 доступ. запрещении"; оЬ1.сгее гевоитсе(); 1Г(оЬ2.пес тевоитсе()] // сап вс111 са11 ивьпя оЬйесс вупсах соис « "Теперь объект оЬ2 может испольэовать ресурс1п"; тееитп Ог Статические функции-члены имеют ограниченный круг приложений, однако они бывают полезны лля предварительной инициализации закрытых статических переменных-членов ло создания реальных объектов.
Например, следуюн(ая программа абсолютно верна. «1пс1ис]е <Товстеащ> ив1пя пащеврасе ве<]; с1авз веае1с Суре всасьс 1пс риЬ11с: всас1с чоЫ 1п1с(1пс х) (1 = х;) чоЫ виси(] (соис « 1;) )у 1пе веаетс Суре:."Тг // определяем переменную 1 ьпс щаьп() // Инициализируем статические данные перед созданием обьекта веаетс Суре::ьпье(100); всасгс суре х; х.вном(]; // Отображаем число 100 теешп 0; Вызов конструкторов и деструкторов Как правило. конструктор объекта вызывается при создании объекта, а деструктор — при его уничтожении. Точный смысл этих собьпий мы рассмотрим ниже. Часть й. Язык С++ Конструкторы локальных объектов последовательно вызываются при их обьявлении.