ОТ РЕДАКТОРА
Книга, которую вы держите в руках, не нуждается в представлении. Кому из серьезных программистов на C++ не известен Web-узел Guru of the Week и его автор Герб Саттер? На основе представленных на этом Web-узле материалов Саттер издал две книги - Exceptional C++ и More Exceptional C++, и в настоящее время работает над очередной книгой этой серии.
В связи с тем, что книга More Exceptional C++ по сути представляет собой продолжение Exceptional C++, было принято решение объединить эти книги при издании на русском языке в одну. Благодаря четкому разделению материала книг по темам и практически идентичному стилю книг в результате получилось не механическое объединение двух книг под одной обложкой, а единая книга, вобравшая в себя опыт множества программистов высочайшего уровня.
Изложение материала в виде задач и их решений позволяет не просто получить теоретические знания, но и тут же закрепить их путем применения на практике. Строгое разделение материала книги по темам позволяет не просто прочесть ее один раз, но и использовать ее как настольную книгу, в которой всегда можно найти подсказку о том, как решать проблемы, возникающие перед вами в процессе работы над реальными проектами.
Следует сказать несколько слов об особенностях перевода книги на русский язык. Постоянно растущая сложность языка программирования C++ вносит свои коррективы в связанную с ним терминологию. Об особенностях русскоязычной терминологии C++, использованной при работе над данной книгой, достаточно полно рассказано в предисловии к русскому изданию книги. В частности, это касается перевода термина statement как инструкция, а не как оператор, который в C++ имеет свое четко определенное значение. Впрочем, для серьезного программиста, на которого и рассчитана данная книга, смысл того или иного перевода очевиден из контекста.
В заключение хотелось бы поблагодарить Герба Саттера не только за замечательную книгу, но и за ряд пояснений и комментариев, полученных от него в процессе работы над русским изданием. Особую благодарность за помощь и советы при работе над переводом книги редакция выражает Александру Кротову (NIXU Ltd).
ПРЕДИСЛОВИЯ
Это - замечательная книга, но только заканчивая ее читать, я понял, до какой степени она замечательна. Возможно, это первая книга, написанная для тех, кто хорошо знаком с C++ - всем C++. От базовых возможностей языка до компонентов стандартной библиотеки и современных технологий программирования - эта книга ведет нас от задачи к задаче, заставляя все время быть начеку и акцентируя все наше внимание, - как и реальные программы на C++. Здесь перемешано все - проектирование классов, поведение виртуальных функций, зависимости компиляции, операторы присваивания, безопасность исключений: Здесь все, как в реальных программах на C++. В книге водоворот из возможностей языка, библиотечных компонент, технологий программирования - водоворот, который завораживает и притягивает. Так же, как и реальные программы на C++:
Когда я сравниваю свои решения задач из книги с ответами автора, я очень часто вижу, что в очередной раз попал в подготовленную ловушку - гораздо чаще, чем мне того хотелось бы. Некоторые могут сказать, что это доказывает лишь, что я не так хорошо знаю C++. Другие сочтут это показателем того, насколько сложен C++, и что никто не в состоянии стать настоящим мастером в программировании на C++. Я же считаю, что это всего лишь указатель на то, что, программируя на C++, надо всегда быть предельно внимательным и иметь ясное представление о том, что именно ты делаешь. C++ - мощный язык, созданный для решения различных задач, и при его использовании очень важно все время оттачивать свое знание языка, его библиотеки и идиом программирования. Широта изложенного материала в данной книге поможет вам в этом.
Читатели-ветераны групп новостей, посвященных C++, знают, насколько трудно оказаться объявленным "Гуру недели" (Guru of the Week). Ветераны-участники знают об этом еще лучше. В Internet, само собой, каждую неделю может быть только один гуру, но, снабженные информацией этой книги, вы можете рассчитывать на то, что каждая ваша программа будет иметь качество, говорящее о том, что над ней работал настоящий гуру.
Скотт Мейерс (Scott Meyers), июнь 1999 г.
Как стать экспертом? Ответ один и тот же для любой области человеческой деятельности.
1. Изучить основы.
2. Изучать этот же материал снова, но в этот раз сконцентрироваться на деталях, важность которых вы не могли осознать во время первого чтения.
Если вы обратите внимание на нужные детали и подробности и овладеете соответствующими знаниями, вы существенно приблизитесь к уровню эксперта. Но, пока вы еще не эксперт, как определить, на какие именно детали следует обратить особое внимание? Вы гораздо быстрее поднимите свой уровень и получите гораздо большее удовлетворение от изучения, если найдется кто-то, кто сможет выбрать эти детали для вас.
В качестве примера я хочу рассказать, как я однажды познакомился с владельцем небольшой фотостудии Фредом Пикером (Fred Picker). Он рассказал, что в фотографии есть две основные сложности: куда направить камеру и когда нажать спуск. Затем он потратил немало времени, рассказывая о таких технических деталях, как экспозиция, проявление и печать, - деталях, которые следует хорошо знать, чтобы иметь возможность со знанием дела сконцентрироваться на основных "сложностях".
В C++, как описано ниже, наиболее интересный способ изучения деталей - пытаться отвечать на вопросы о программах на C++, например такие.
- Одинаково ли действие "f(a++);" и "f(a); ++a;"?
- Можно ли использовать итератор для изменения содержимого контейнера set?
- Предположим, что вы используете vector v, который вырос до очень большого размера. Вы хотите очистить вектор и вернуть память системе. Поможет ли вам в этом вызов v.clear()?
Вы, вероятно, догадываетесь, что ответы на эти простые вопросы должны быть "нет", иначе зачем бы я вас об этом спрашивал? Но знаете ли вы, почему они отрицательны? Вы уверены?
Эта книга отвечает на все перечисленные и множество других не менее интересных вопросов о казалось бы простых программах. Имеется немного других книг, подобных этой. Большинство посвященных C++ книг, претендующих на звание книг "для профессионалов", либо посвящено узкоспециализированным темам (что неплохо, если вы хотите повысить свои знания и умения в этой конкретной области, но не совсем годится для получения более глубоких знаний для ежедневного применения), либо это "для профессионалов" указано просто для привлечения читателей.
Тщательно разобравшись с вопросами и ответами в этой книге, вам больше не придется задумываться над деталями написания ваших программ, и вы сможете полностью сконцентрироваться на решении стоящей перед вами задачи.
Эндрю Кёниг (Andrew Koenig), июнь 2001 г.
ВВЕДЕНИЕ
Греческий философ Сократ обучал своих учеников, задавая им вопросы, которые были разработаны таким образом, чтобы руководить учениками и помогать им сделать верные выводы из того, что они уже знают, а также показать им взаимосвязи в изучаемом материале и этого материала с другими знаниями. Этот метод обучения стал так знаменит, что сегодня мы называем его "методом Сократа". С точки зрения учащихся подход Сократа включает их в процесс обучения, заставляет думать и помогает связать и применить уже имеющиеся знания к новой информации.
Эта книга предполагает, что вам приходится заниматься написанием промышленного программного обеспечения на языке C++, и использует вопросы и ответы для обучения эффективному использованию стандарта C++ и его стандартной библиотеки, ориентируясь на разработку надежного программного обеспечения с использованием всех современных возможностей C++. Многие из рассмотренных в книге задач появились в результате работы автора и других программистов над своими программами. Цель книги - помочь читателю сделать верные выводы, как из хорошо известного ему материала, так и из только что изученного, и показать взаимосвязь между различными частями C++.
Данная книга не посвящена какому-то конкретному аспекту C++. Нельзя, однако, сказать, что она охватывает все детали C++ - для этого потребовалось бы слишком много книг, - но, тем не менее, в ней рассматривается широкая палитра возможностей C++ и стандартной библиотеки и, что немаловажно, показывается, как кажущиеся на первый взгляд несвязанными между собой вещи могут совместно использоваться для получения новых решений старых хорошо известных задач. Здесь вы обнаружите материал, посвященный шаблонам и пространствам имен, исключениям и наследованию, проектированию классов и шаблонам проектирования, обобщенному программированию и магии макросов, - и не просто винегрет из этих тем, а задачи, выявляющие взаимосвязь всех этих частей современного C++.
Большинство задач первоначально было опубликовано в Internet и некоторых журналах; в частности это расширенные версии первых 62 задач, которые можно найти на моем узле Guru of the Week [GotW], а также материалы, опубликованные мною в таких журналах, как C/C++ User Journal, Dr. Dobb's Journal, бывшем C++ Report и др.
Что следует знать для чтения этой книги
Я полагаю, что читатель уже хорошо знаком с основами C++. Если это не так, начните с хорошего введения и обзора по C++. Для этой цели могу порекомендовать вам такие книги, как [Stroustrup00], [Lippman98], а также [Meyers96] и [Meyers97].
Как читать данную книгу
Название задачи и уровень ее сложности подсказывают вам ее предназначение. Замечу, что уровень сложности задач - мое субъективное мнение о том, насколько сложно будет решить ту или иную задачу большинству читателей, так что вы вполне можете обнаружить, что задача с уровнем сложности 7 решена вами гораздо быстрее, чем задача с уровнем сложности 5.
Чтение книги от начала до конца - неплохое решение, но вы не обязаны поступать именно так. Вы можете, например, читать только интересующие вас разделы книги. За исключением того, что я именую "мини-сериями" (связанные между собой задачи с одинаковым названием и подзаголовками "Часть 1", "Часть 2" и т.д.), задачи в книге практически независимы друг от друга, и вы можете совершенно спокойно читать их в любом порядке. Единственная подсказка: мини-серии лучше читать вместе; во всем остальном - выбор за вами.
В этой книге немало рекомендаций, в которых следующие слова имеют особое значение.
- Всегда. Это абсолютно необходимо; не пренебрегайте данной рекомендацией.
- Предпочтительно. Обычно лучше поступать так, как сказано. Поступать иначе можно только в тех случаях, когда ситуация настоятельно того требует.
- Избегайте. Обычно поступать так - не лучший способ, и это может оказаться опасно. Рассмотрите альтернативные способы достижения того же результата. Поступать так можно только в тех случаях, когда ситуация настоятельно того требует.
- Никогда. Это очень опасно, даже не думайте так поступать!
Благодарности
Я выражаю особую признательность редактору серии Бьярну Страуструпу (Bjarne Stroustrup), а также Дебби Лафферти (Debbie Lafferty), Марине Ланг (Marina Lang), Тирреллу Альбах (Tyrrell Albaugh), Чарльзу Ледди (Charles Leddy) и всем остальным из команды Addison-Wesley за их помощь и настойчивость в работе над данным проектом. Трудно представить себе лучшую команду для работы над данной книгой; их энтузиазм и помощь помогли сделать эту книгу тем, чем она, я надеюсь, является.
Еще одна группа людей, заслуживающая особой благодарности, - это множество экспертов, чья критика и комментарии помогли сделать материал книги более полным, более удобочитаемым и более полезным. Особую благодарность я хотел бы выразить Бьярну Страуструпу (Bjarne Straustrup), Скотту Мейерсу (Scott Meyers), Андрею Александреску (Andrei Alexandrescu), Стиву Клэймэджу (Steve Clamage), Стиву Дьюхарсту (Steve Dewhurst), Кэю Хорстману (Cay Horstmann), Джиму Хайслопу (Jim Hyslop), Брендону Кехоу (Brendan Kehoe), Дэннису Манклу (Dennis Mancl), Яну Кристиану ван Винклю (Jan Christiaan van Winkel), Кэвлину Хенни (Kevlin Henney), Эндрю Кёнигу (Andrew Koenig), Патрику Мак-Киллену (Patric McKillen) и ряду других анонимных рецензентов. Все оставшиеся в книге ошибки, описки и неточности - только на моей совести.
И наконец, огромное спасибо моей семье и друзьям за то, что они всегда рядом, - как в процессе работы над этим проектом, так и в любое другое время.
Герб Саттер (Herb Sutter)