Г. Шилтд - Самоучитель C++ (PDF) (1114887), страница 86
Текст из файла (страница 86)
Ответы на вопросы и решения упражнений641// Использование оператора new(nothrow)Shape *generator()IShape *temp;s w i t c h ( r a n d ( ) % 4) {case 0:returncase 1:returncase 2:returncase 3:returnnew(nothrow) Line;new(nothrow) Rectangle;new(nothrow) Triangle;new(nothrow) NullShape;if(temp) return temp;else return NULL;JГЛАВА 13Повторение пройденного1. Помимо обычных для языка С операторов приведения типов, в C++ поддерживаются дополнительные операторы, которые перечислены ниже:ОператорНазначениеdynamic_castreinterpret_castВыполняет операцию приведения полиморфных типовПреобразует указатель на один тип в указатель на другой типstatic_castВыполняет операцию "обычного" приведения типовconst_castЛишает объекты атрибута const2.
Класс type_info — это класс, который инкапсулирует информацию о типеданных. Ссылка на объект типа typejmfo является возвращаемым значениемоператора typeid.3. С помощью оператора typeid.4. if(typeid(Derived) == typeid(p*))cout « "Указатель р указывает на объект класса Derived\n";elsecout « "Указатель р указывает на объект класса Base\n";642Самоучитель C++5. Пропущено слово "производного".6. Нет.Упражнения13-11. /* Программа превращения пробелов в вертикальные линии |без использования инструкции "using namespace std"*/^include <iostream>linclude <fstream>int main(int argc, char *argv[])*if(argc!=3) {std::cout « "Преобразование <файл_ввода> <файл_вывода>Хп";return 1;1std::ifstream fin(argv[l]); // открытие файла для вводаstd::ofstream fout(argv[2]); // создание файла для выводаif(!fout) {std::cout « "Файл открыть невозможноХп";return 1;if(!fin) {std::cout « "Файл открыть невозможноХп";return 1;char ch;fin.unsetf{std::ios::skipws); // не пропускать пробелыwhile{!fin.eof(}) {fin » ch;if (ch—1 '} ch = ' | ';1if(Ifin.eof()) fout « ch;fin.close();fout.close();return 0;Приложение В.
Ответы на вопросы и решения упражнений6432. Безымянное пространство имен ограничивает область видимости идентификаторов тем файлом, в котором они объявлены.3. Представленная ниже форма инструкции using вводит в текущее пространство имен только указанный в инструкции член:using имя_пространства;:член;Следующая форма инструкции using делает видимым все пространство имен:using namespace кмя_пространстаа;4.
Поскольку вся стандартная библиотека C++, включая потоки cin и cout, объявлена в пространстве имен std, для совместимости большинство программнужно вводить в пространство имен std. Это дает возможность использоватьв программах имена стандартной библиотеки C++ непосредственно, безуточнения, к какому пространству имен они принадлежат.
Для большинствапрограмм альтернативой была бы необходимость задания всех ссылок наимена стандартной библиотеки с инструкцией std::. Другой альтернативойявляются инструкции using только для потоков, т. е. using std::cin и usingstd::cout.5. Размещая код библиотеки в собственном пространстве имен, вы снижаетевероятность возникновения конфликтов имен.13.21. // Преобразование строки в целое^include <iostreara>#include <cstring>using namespace std;class strtype {char str[80];int len;public:strtype(char *s) { strcpy(str, s); len = strlen(s); }operator char *() { return str; }operator int() { return len; }int main ()strtype s("Функции преобразования весьма удобны");char *p;int 1;1 = s; // преобразование строки s в целое — длину строкир = s; // преобразование строки s644___Самоучитель C++// в char * — указатель на строкуcout « "Строка: \п";cout « р « "\пимеет длину " « 1 « " символов .
\п" ;return 0;J2. ^include <iostream>using namespace std;int p(int base, int exp) ;class pwr (int base;int exp;public:pwr (int b, int e) { base = b; exp = e; }operator int() f return p(base, exp}; }// Возвращает основание base в степени expint p(int base, int exp)' int temp;for(temp=l; exp; exp — ) temp = temp * base;return temp;int main()pwr ol(2, 3), o2(3, 3);int result;result = ol;cout « result « '\n';result = o2;cout « result « '\n';// объекты можно указывать непосредственно в инструкции cout,// как это сделано здесьcout « ol + 100 « '\n';return 0;}13.31. // Пример разделения ресурса с трассировкой работы#include <iostream>Приложение_RОтветынавопросыирешенияупражнений_645^include <cstring>using namespace std;class output {static char outbuf [255] ; // это разделяемый ресурсstatic int inuse; // если переменная inuse равна О,// буфер доступен; иначе он занятstatic int oindex; // индекс буфераchar str[80] ;int i; // индекс следующего символа в strint who; // идентификатор объекта, должен быть положительнымpublic :output{int w, char *s) ( strcpy(str, s) ; i = 0; who = w; }/* Эта функция возвращает -1 при ожидании освобождения буфера, онавозвращает 0 при завершении вывода, и она возвращает who, если буфервсе еще используется*/int putbuf ( ){if(!str[i]) { // вывод законченinuse =0; // освобождение буфераreturn 0; // сигнал завершения}if (! inuse) inuse = who; // захват буфераif(inuse != who) (cout « "Процесс" « who « "сейчас блокирован \п";return -1; // буфер использует кто-то еще}if (str [i]) { // символы все еще выводятсяoutbuf [oindex] = str[i];cout « "Процесс " « who « " выводит символы\п";i++; oindex++;outbuf [oindex] = r\0'; // последним всегда идет нульreturn 1;}return 0;}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, " статических переменных");Самоучитель C++while(ol.putbuf() I o 2 .
p u t b u f ( ) ) ; // вывод символово Д..show();return 0;I2. ^include <iostream># include <new>using namespace std;class test {static int count;public:testC) { count-t-+; }~test() { count — ; }int getcountO { return count; }int test::count = 0;int main()test ol, o2, o3;cout « ol.getcount() « " объектов существуетХп";test *p;/* Отслеживание ошибок выделения памяти с помощью старого и новогомеханизмов обработки ошибок*/try {р = new test; // выделение памяти объектуif(!p) { // старый стильcout « "Ошибка выделения памятиХп";return 1;} catch(bad_alloc ba) { // новый стильcout « "Ошибка выделения памяти\п";return 1;cout « ol.getcount () ;cout « " объектов существует после выделения памяти\п// удаление объектаdelete р;cout « ol.getcount {};Приложение В.
Ответы на вопросы и решения упражнений647cout « " объектов существует после удаленияХп";return 0;13.41. Для исправления программы просто сделайте переменную current модифицируемой, чтобы ее можно было изменить с помощью постоянной функциичлена countingO Решение упражнения представлено ниже:// Теперь программа исправленаttinclude <iostream>using namespace std;class CountDown {int incr;int target;mutable int current; // делаем переменную current модифицируемойpublic:CountDown (int delay, int i = 1) (target = delay;incr = i;current = 0;ibool counting ( ) const {current +- incr;if {current >= target) {cout « "\a";return false;}cout « current « " ";return true;int mainO{CountDown ob(100, 2 ) ;while (ob.
counting ( ) ) ;return 0;12. Нет, не может. Если бы у постоянной функции-члена была возможность вызвать не постоянную функцию-член, то не постоянную функцию-член можно было бы использовать для модификации вызывающего объекта.648Самоучитель С_+_+_13.51- Да2. Да, поскольку в C++ определено автоматическое преобразование из типа intв тип double.3. Одна из проблем неявного преобразования конструкторов состоит в возможности просто забыть, что такое преобразование имело место. Например,неявное преобразование в инструкции присваивания очень напоминает перегруженный оператор присваивания, хотя их действия не обязательно аналогичны.
Когда вы создаете классы, предназначенные для широкого использования, чтобы не вводить в заблуждение потенциальных пользователей ваших классов, было бы правильным отказаться от неявного преобразованияконструкторов.13.71. /* В этой версии программы на экран выводится число символов,записанных в буфер*/^include <iostream>^include <strstream>using namespace std;int main{){char buf[255];ostrstream ostr(buf, sizeof buf);ostr « "ввод/вывод через массивы работает с потокамиХп";ostr « "точно так же, как обычный ввод/вывод\п " « 103;ostr « ' ' « 123.23 « '\п';// можно также использовать манипуляторыostr « hex « 100 « ' ';// или флаги форматаostr.setf(ios::scientific);ostr « dec « 123.23;ostr « endl « ends; // гарантия того,// что буфер завершится нулем// вывод на экран содержимого буфераcout « buf;cout « ostr.pcount();return 0;ПриложениеВ.Ответынавопросыирешенияупражнений2.
/* Массивы в качестве объектов ввода/вывода при копированиисодержимого одного массива в другой*/^include <iostream>#include <strstream>using namespace std;char inbuf[] = "Это проверка ввода/вывода C++, основанного наиспользовании символьных массивов";char outbuf [255] ;int main (){istrstream istr(inbuf);ostrstream ostr (outbuf , sizeof outbuf};char ch;while ( ! istr.eof () ) {istr.get (ch) ;if (listr.eof ()) ostr. put {ch) ;}ostr.
put (' \0' ); // нулевой символ завершенияcout « "Ввод: " « inbuf « '\n';cout « "Вывод: " « outbuf « '\n';return 0;3. // Преобразование строки в число с плавающей точкой#include <iostream>#include <strstream>using namespace std;int main(){float f;char s [ ] = "1234.564"; // вещественное в виде строкиistrstream istr(s);// Простой способ преобразования строки// в ее внутреннее представлениеistr » f;cout « "Преобразованная форма: " « f « '\n';return 0;_649650Самоучитель C++Проверка усвоения материала главы 131. В отличие от обычных переменных-членов, для которых характерно то, что вкаждом объекте класса имеется их копия, у статической переменной-членасуществует только одна копия, которую все объекты класса используютсовместно.2.