C++
C++ читать книгу онлайн
С++ – это универсальный язык программирования, задуманный так, чтобы сделать программирование более приятным для серьезного программиста. За исключением второстепенных деталей С++ является надмножеством языка программирования C. Помимо возможностей, которые дает C, С++ предоставляет гибкие и эффективные средства определения новых типов. Используя определения новых типов, точно отвечающих концепциям приложения, программист может разделять разрабатываемую программу на легко поддающиеся контролю части. Такой метод построения программ часто называют абстракцией данных. Информация о типах содержится в некоторых объектах типов, определенных пользователем. Такие объекты просты и надежны в использовании в тех ситуациях, когда их тип нельзя установить на стадии компиляции. Программирование с применением таких объектов часто называют объектно-ориентированным. При правильном использовании этот метод дает более короткие, проще понимаемые и легче контролируемые программы.
Ключевым понятием С++ является класс. Класс – это тип, определяемый пользователем. Классы обеспечивают сокрытие данных, гарантированную инициализацию данных, неявное преобразование типов для типов, определенных пользователем, динамическое задание типа, контролируемое пользователем управление памятью и механизмы перегрузки операций. С++ предоставляет гораздо лучшие, чем в C, средства выражения модульности программы и проверки типов. В языке есть также усовершенствования, не связанные непосредственно с классами, включающие в себя символические константы, inline-подстановку функций, параметры функции по умолчанию, перегруженные имена функций, операции управления свободной памятью и ссылочный тип. В С++ сохранены возможности языка C по работе с основными объектами аппаратного обеспечения (биты, байты, слова, адреса и т.п.). Это позволяет весьма эффективно реализовывать типы, определяемые пользователем.
С++ и его стандартные библиотеки спроектированы так, чтобы обеспечивать переносимость. Имеющаяся на текущий момент реализация языка будет идти в большинстве систем, поддерживающих C. Из С++ программ можно использовать C библиотеки, и с С++ можно использовать большую часть инструментальных средств, поддерживающих программирование на C.
Эта книга предназначена главным образом для того, чтобы помочь серьезным программистам изучить язык и применять его в нетривиальных проектах. В ней дано полное описание С++, много примеров и еще больше фрагментов программ.
Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних чтение данного контента СТРОГО ЗАПРЕЩЕНО! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту [email protected] для удаления материала
Если не задано поле нулевой длины, то будет производится усечение или дополнение; иначе будет использоваться столко символов (ровно), сколько нужно. Например:
cout «« "dec(" «« x «« ") = oct(" «« oct(x,6) «« ") = hex(" «« hex(x,4) «« ")";
Если x==15, то в результате получится:
dec(15) = oct( 17) = hex( f);
Можно также использовать строку в общем формате:
char* form(char* format ...);
cout««form() эквивалентно применению стандартной функции вывода языка C printf()*. form() возвращает строку, получамую в результате преобразования и форматирования ее парамеров, которые стоят после первого управляющего параметра – строки формата format. Строка формата состоит из объектов двух типов: обычных символов, которые просто копируются в пток вывода, и спецификаций преобразования, каждая из которых влечет преобразование и печать следующего из параметров. Кадая спецификация преобразования начинается с символа %. Наример:
– * Объяснение того, как применяются строки формата, – это слегка отредактированный вариант спецификации printf(). (прим. автора)
cout«„form(«there were %d members present“,no_of_members);
Здесь %d указывает, что no_of_members должно рассматрваться как int и печататься в виде соответствующей последовтельности десятичных цифр. Если no_of_members==127, вывод бдет такой:
there were 127 members present
Множество спецификаций преобразования довольно велико и обеспечивает высокую степень гибкости. После % может стоять:
– необязательный знак минус, который задает выравнивание преобразованного значения влево в указанном поле;
d необязательная строка цифр, задающая ширину поля. Если преобразованное значение имеет меньше цифр, чем ширина поля, оно будет дополняться пробелами слева (или справа, если был задан индикатор выравнивания влево) до заполнния всей ширины поля; если ширина поля начинается с нля, то вместо дополнения пробелами будет делаться допонение нулями;
. необязательная точка, для отделения ширины поля от
следующей строки цифр;
d необязательная строка цифр, специфицирующая точность, которая задает число цифр после десятичной точки для преобразований e и f или печатаемых символов для строки;
* в ширине поля или точности вместо строки цифр может стять *. В этом случае ширина поля и точность задается цлым параметром;
h необязательный символ h; указывает на то, что идущие за ним d, o, x или y соответствуют параметру короткое цлое;
l необязательный символ h; указывает на то, что идущие за ним d, o, x или y соответствуют параметру длинное целое;
% указывает, что должен быть напечатан символ %, никакие параметры при этом не затрагиваются;
c символ, указывающий, какой тип преобразования должен применяться. Символы преобразования и их значения таквы:
d целый параметр преобразуется в десятичную запись;
o целый параметр преобразуется в восьмеричную запись;
x целый параметр преобразуется в шестнадцатиричную запись;
f параметр float или double преобразуется в десятичную запись вида [-]ddd.ddd, где число, задаваемое цифрами d после десятичной точки, эквивалентно спецификации тоности для параметра. Если точность опущена, дается шесть цифр; если точность явно задана как 0, то не печатается десятичная точка и не печатается ни одной цифры;
e параметр float или double преобразуется в десятичную запись вида [-]d.ddde+dd, где перед десятичной точкой стоит одна цифра, а число, задаваемое цифрами после дсятичной точки, эквивалентно спецификации точности для параметра; когда точность опущена, выдается шесть цифр;
g параметр float или double печатается в том из видов d, f или e, который обеспечивает полную точность при минмальной затрате места;
c печатается символьный параметр, пустые символы игнорруются;
s параметр воспринимается как строка (указатель на сивол), и печатаются символы из строки до пустого символа или до тех пор, пока не будет достигнуто число символов, указанное спецификацией точности; но если точность равна нулю, печатаются все символы до пустого;
u беззнаковый целый параметр преобразуется в десятичную запись.
Несуществующая или недостаточная ширина поля никогда не приводит к обрезанию поля; дополнение поля записи имеет место только в том случае, если указанная ширина поля превышает фактическую ширину.
Вот более сложный пример:
char* src_file_name;
int line; char* line_format = «n#line %d »%s"n"; //... cout «„ „int a;n“; cout «« form(line_format,line,src_file_name); cout «« «int b;n“;
который печатает
int a;
#line 13 «С++/main.c» int b;
Применение form() небезопасно в смысле того, что не вполняется проверка типа. Вот, например, хорошо хорошо извесный способ получить непредсказуемый вывод и/или дамп (core dump):
char x; // ... cout«„form(«bad input char: %s“,x);
Правда, она дает большую гибкость в том виде, который хорошо знаком программистам на C. Потоковый вывод можно смшивать с выводом в стиле printf().
В настоящее время нет полностью удовлетворительных средств, обеспечивающих форматированный вывод типов, опредляемых пользователем* В частности, вероятно нужно будет найти стандартный способ передавать функции вывода для определяемго пользователем типа информацию, которая позволит ей опредлить пространственные ограничения, вид заполнения, левое или правое выравнивание и т.п. такими, какими они определяются в ее вызове. Вполне осуществимый, но не идеальный подход состит в том, чтобы снабжать определяемый пользователем тип фунциями, которые порождают соответствующее строковое предсталение объекта, для которого они вызываются, аналогично форматирующим функциям oct(), hex() и т.д. Например:
class complex (* float re,im; public: // ... char* string(char* format) (* return form(format,re,im); *) *); // ... cout «„ z.string(«(%.3f,%.3f)“);
Память для хранения строк, которые возвращают form(), hex() и т.п., берется из одного статически размещаемого цилического буфера, поэтому не имеет смысла сохранять указтель, возвращаемый любой из этих функций, для дальнейшего ипользования. Указываемые символы будут меняться.
8.2.5 Виртуальная функция вывода
Иногда функция вывода должна быть virtual. Рассмотрим пример класса shape, который дает понятие фигуры (#1.18):
class shape (* // ... public: // ... virtual void draw(ostream amp; s); // рисует «this» на "s" *);
class circle : public shape (* int radius; public: // ... void draw(ostream amp;); *);
То есть, круг имеет все признаки фигуры и может обрабтываться как фигура, но имеет также и некоторые специальные свойства, которые должны учитываться при его обработке.
Чтобы поддерживать для таких классов стандартную пардигму вывода, операция «« определяется так:
ostream amp; operator«„(ostream amp; s, shape* p) (* p-“draw(s); return s; *)
Если next – итератор типа определенного в #7.3.3, то список фигур распечатывается например так:
while ( p = next() ) cout «« p;
8.3 Файлы и потоки
Потоки обычно связаны с файлами. Библиотека потоков содает стандартный поток ввода cin, стандартный поток вывода cout и стандартный поток ошибок cerr. Программист может отрывать другие файлы и создавать для них потоки.
8.3.1 Инициализация потоков вывода
ostream имеет конструкторы:
class ostream (* // ... ostream(streambuf* s); // связывает с буфером потока ostream(int fd); // связывание для файла ostream(int size, char* p); // связывает с вектором *);
Главная работа этих конструкторов – связывать с потоком буфер. streambuf – класс, управляющий буферами; он описываеся в #8.6, как и класс filebuf, управляющий streambuf для файла. Класс filebuf является производным от класса streambuf.
Описание стандартных потоков вывода cout и cerr, которое находится в исходных кодах библиотеки потоков ввода/вывода, выглядит так: