Г. Шилтд - Самоучитель C++ (PDF) (1114887), страница 58
Текст из файла (страница 58)
Вспомните, функцияstrcpyO имеет следующий прототип:char *strcpy(char *sl, const char *s2) ;Поскольку прототип определяет, что объект s2 имеет тип char *, функцияпреобразования объекта в тип char * вызывается автоматически. Этот примерпоказывает, как функция преобразования может помочь интегрировать вашиклассы в библиотеку стандартных функций C++.Упражнения)1. Используя класс strtype из примера 2, создайте функцию преобразования дляпревращения строки в целое. Функция преобразования должна возвращатьдлину строки, хранящейся в str.
Покажите, что ваша функция преобразования работает.2. Пусть дан класс:class pwr (int base;int exp;public:pwr{int b, int e) { base = b; exp = e; }// здесь создайте функцию преобразования в целое3. Создайте функцию преобразования для превращения объекта типа pwr в целое. Функция должна возвращать результат возведения в степень baseexp.396Самоучитель C++13.3. Статические члены классаПеременные — члены класса можно объявлять как статические (static). Используя статические переменные-члены, можно решить несколько непростых проблем.
Если вы объявляете переменную статической, то может существовать только одна копия этой переменной — независимо от того, сколькообъектов данного класса создается. Каждый объект просто использует(совместно с другими) эту одну переменную.
Запомните, для обычных переменных-членов при создании каждого объекта создается их новая копия,и доступ к каждой копии возможен только через этот объект. (Таким образом, для обычных переменных каждый объект обладает собственными копиями переменных.) С другой стороны, имеется только одна копия статической переменной — члена класса, и все объекты класса используют ее совместно. Кроме этого, одна и та же статическая переменная будетиспользоваться всеми классами, производными от класса, в котором этастатическая переменная содержится.Может показаться необычным то, что статическая переменная — член класса создается еще до того, как создан объект этого класса.
По сути, статический член класса — это просто глобальная переменная, область видимостикоторой ограничена классом, в котором она объявлена. В результате, как выузнаете из следующих примеров, доступ к статической переменной-членувозможен без всякой связи с каким бы то ни было объектом.Когда вы объявляете статические данные-члены внутри класса, вы не определяете их. Определить их вы должны где-нибудь вне класса. Для тогочтобы указать, к какому классу статическая переменная принадлежит, вамнеобходимо переобъявить (redeclare) ее, используя операцию расширенияобласти видимости.Все статические переменные-члены по умолчанию инициализируются нулем. Однако, если это необходимо, статической переменной класса можнодать любое выбранное начальное значение.Запомните, что основной смысл поддержки в C++ статических переменных-членов состоит в том, что благодаря им отпадает необходимость в использовании глобальных переменных.
Как можно предположить, если приработе с классами задавать глобальные переменные, то это почти всегда нарушает принцип инкапсуляции, являющийся фундаментальным принципомOOP и C++.Помимо переменных-членов статическими можно объявлять и функциичлены, но обычно это не делается.
Доступ к объявленной статическойфункции — члену класса возможен только для других статических членовэтого класса. (Естественно, что доступ к объявленной статической функции — члену класса возможен также и для глобальных данных и функций.)У статической функции-члена нет указателя this. Статические функциичлены не могут быть виртуальными. Статические функции-члены не могутГлава 13. Пространства имен и другие темы397объявляться с идентификаторами const (постоянный) и volatile (переменный). И наконец, статические функции — члены класса могут вызыватьсялюбым объектом этого класса, а также через имя класса и оператор расширения области видимости без всякой связи с каким бы то ни было объектомэтого класса.Примерь!""•^igj^1.
Простой пример использования статической переменной-члена.// Пример статической переменной-членаttinclude <iostream>using namespace std;class myclass {static int i;public:void seti(int n) { i = n; }int geti(} { return i; }// Определение myclass: :i. Переменная i по-прежнему// остается закрытым членом класса myclassint myclass : :i;int main(){myclass ol, o2;ol.seti(lO);cout « "ol.i: " « ol.getiO « T\n'; // выводит значение 10cout « "o2.i: " « o2.geti() « '\np; // также выводит 10return 0;После выполнения программы на экране появится следующее:ol.i:o2.i:1010Глядя на программу, можно заметить, что фактически только для объекта olустанавливается значение статической переменной-члена i.
Однако поскольку переменная i совместно используется объектами ol и о2 (и, на самом деле, всеми объектами типа myclass), оба вызова функции geti() дают один итот же результат.398Самоучитель C++Обратите внимание, что переменная i объявляется внутри класса myclass, ноопределяется вне его. Этот второй шаг гарантирует, что для переменной i будет выделена память. С технической точки зрения, определение класса является всего лишь определением типа и не более. Память для статической переменной при этом не выделяется. Поэтому для вьщеления памяти статической переменной-члену требуется ее явное определение,2. Поскольку статическая переменная — член класса существует еще до создания объекта этого класса, доступ к ней в программе может быть реализованбез всякого объекта.
Например, в следующем варианте предыдущей программы для статической переменной i устанавливается значение 100 без всякой ссылки на конкретный объект. Обратите внимание на использованиеоператора расширения области видимости для доступа к переменной i.// Для обращения к статической переменной объект не нуженtfinclude <iostream>using namespace std;class myclass {public:static int i;void seti{int n) { i = n; }int g e t i ( ) { return i; }int myclass::i;int main ()myclass ol, o2;// непосредственное задание значения переменной imyclass::! = 100; // объекты не упоминаютсяcout « "ol.i: " « ol.geti() « '\n'; // выводит 100cout « "o2.i: " « o2.geti{) « '\n'; // также выводит 100return 0;}Так как статической переменной i присвоено значение 100, программа выводит на экран следующее:ol.i: 100o 2 .
i : 1003. Традиционным использованием статических переменных класса являетсякоординация доступа к разделяемым ресурсам, таким как дисковая память,принтер или сетевой сервер. Как вы уже, вероятно, знаете из своего опыта,координация доступа к разделяемым ресурсам требует некоторых знаний оГлава 13. Пространства имен и_другие темы399последовательности событий. Чтобы понять, как с помощью статических переменных-членов можно управлять доступом к разделяемым ресурсам, изучите следующую программу. В ней создается класс output, который поддерживает общий выходной буфер outbnf, являющийся статическим символьныммассивом.
Этот буфер используется для получения выходной информации,передаваемой функцией-членом outbuf(). Эта функция посимвольно передаетсодержимое строки str. Сначала функция запрашивает доступ к буферу, а затем передает в него все символы str. Функция предотвращает доступ в буфердругим объектам до окончания вывода. Понять работу программы можно покомментариям к ней.// Пример разделения ресурсовttinclude <iostream>^include <cstring>using namespace std;class output {static char outbuf[255]; // это разделяемые ресурсыstatic int inuse; // если переменная inuse равна О,// буфер доступен; иначе — нетstatic int oindex; // индекс буфераchar atr[80];int i; // индекс следующего символа строкиint who; // идентификатор объекта должен быть положительнымpublic:output(int w, char *s) {strcpy(str r s); i = 0; who = w;}/* Эта функция возвращает -1 при ожидании буфера; 0 — при завершениивывода; who — если буфер все еще используется.*/int putbuf(){if(!str[i]) { // вывод завершенinuse =0; // освобождение буфераreturn 0; // признак завершения}if (!inuse) inuse = who; // захват буфераif(inuse != who) return -1; // буфер кто-то используетif(str[i]) { // символы еще осталисьoutbuf[oindex] = str[i];i++; oindex++;outbuf[oindex] = '\0'; // последним всегда идет нульreturn 1;return 0;400Самоучитель C++void show() { cout « outbuf « '\n';}};char output::outbuf[255]; // это разделяемые ресурсыint output::inuse = 0; // если переменная inuse равна О,// буфер доступен; иначе — нетint output::oindex = 0; // индекс буфераint main(){output ol(l,"Это проверка " ) , о2{2,"статических переменных");while (ol.putbuf{) I o 2 .