Стенли Липпман - Язык программирования C++. Пятое издание
- Название:Язык программирования C++. Пятое издание
- Автор:
- Жанр:
- Издательство:Издательский дом Вильямс
- Год:2014
- Город:Москва
- ISBN:978-5-8459-1839-0
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Стенли Липпман - Язык программирования C++. Пятое издание краткое содержание
Вы держите в руках новое издание популярного и исчерпывающего бестселлера по языку программирования С++, которое было полностью пересмотрено и обновлено под
. Оно поможет вам быстро изучить язык и использовать его весьма эффективными и передовыми способами. В соответствии с самыми передовыми и современными методиками изложения материала авторы демонстрируют использование базового языка и его стандартной библиотеки для разработки эффективного, читабельного и мощного кода.
С самого начала этой книги читатель знакомится со стандартной библиотекой С++, ее самыми популярными функциями и средствами, что позволяет сразу же приступить к написанию полезных программ, еще не овладев всеми нюансами языка. Большинство примеров из книги было пересмотрено так, чтобы использовать новые средства языка и продемонстрировать их наилучшие способы применения. Эта книга — не только проверенное руководство для новичков в С++, она содержит также авторитетное обсуждение базовых концепций и методик языка С++ и является ценным ресурсом для опытных программистов, особенно желающих побыстрей узнать об усовершенствованиях С++11.
Стенли Б. Липпман Жози Лажойе Барбара Э. Му • Узнайте, как использовать новые средства языка С++11 и стандартной библиотеки для быстрого создания надежных программ, а также ознакомьтесь с высокоуровневым программированием
• Учитесь на примерах, в которых показаны передовые стили программирования и методики проектирования
• Изучите принципы и узнайте почему язык С++11 работает именно так
• Воспользуйтесь множеством перекрестных ссылок, способных помочь вам объединить взаимосвязанные концепции и проникнуть в суть
• Ознакомьтесь с современными методиками обучения и извлеките пользу из упражнений, в которых подчеркиваются ключевые моменты, позволяющие избежать проблем
• Освойте лучшие методики программирования и закрепите на практике изученный материал
Исходный код примеров можно загрузить с веб-страницы книги на сайте издательства по адресу: http://www.williamspublishing.com
Язык программирования C++. Пятое издание - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
(d) Если класс не определяет стандартный конструктор, компилятор сам создает конструктор, который инициализирует каждую переменную-член значением по умолчанию соответствующего типа.
7.5.4. Неявное преобразование типов класса
Как упоминалось в разделе 4.11, язык С++ автоматически осуществляет преобразование некоторых встроенных типов. Обращалось также внимание на то, что классы тоже могут определять неявные преобразования. Каждый конструктор, который может быть вызван с одним аргументом, определяет неявное преобразование в тип класса. Такие конструкторы иногда упоминают как конструкторы преобразования (converting constructor). Определение преобразования из типа класса в другой тип рассматривается в разделе 14.9.
Конструктор, который может быть вызван с одиночным аргументом, вполне позволяет определить неявное преобразование из типа параметра в тип класса.
Конструкторы класса Sales_data, получающие строку и объект класса istream, оба определяют неявные преобразования из этих типов в тип Sales_data. Таким образом, можно использовать тип stringили istreamтам, где ожидается объект типа Sales_data:
string null_book = "9-999-99999-9";
// создает временный объект типа Sales_data
// с units_sold и revenue равными 0 и bookNo равным null_book
item.combine(null_book);
Здесь происходит вызов функции-члена combine()класса Sales_dataсо строковым аргументом. Этот вызов совершенно корректен; компилятор автоматически создаст объект класса Sales_dataиз данной строки. Этот вновь созданный (временный) объект класса Sales_dataпередается функции combine(). Поскольку параметр функции combine()является ссылкой на константу, этому параметру можно передать временный объект.
В разделе 4.11.2 обращалось внимание на то, что компилятор автоматически применит только одно преобразование типов класса. Например, следующий код ошибочен, поскольку он неявно использует два преобразования:
// ошибка: требует двух пользовательских преобразований:
// (1) преобразование "9-999-99999-9" в string
// (2) преобразование временной строки в Sales_data
item.combine("9-999-99999-9");
Если данный вызов необходим, это можно сделать при явном преобразовании символьной строки в объект класса stringили в объект класса Sales_data:
// ok: явное преобразование в string,
// неявное преобразование в Sales_data
item.combine(string("9-999-99999-9"));
// ok: неявное преобразование в string,
// явное преобразование в Sales_data
item.combine(Sales_data("9-999-99999-9"));
Желательно ли преобразование типа stringв Sales_data, зависит от конкретных обстоятельств. В данном случае это хорошая идея. Строка в переменной null_book, вероятнее всего, соответствует несуществующему ISBN.
Преобразование из istreamв Sales_dataболее проблематично:
// использует конструктор istream при создании объекта для передачи
// функции combine
item.combine(cin);
Этот код неявно преобразует объект cinв объект класса Sales_item. Это преобразование осуществляет тот конструктор класса Sales_data, который получает тип istream. Этот конструктор создает (временный) объект класса Sales_dataпри чтении со стандартного устройства ввода. Затем этот объект передается функции same_isbn().
Этот объект класса Sales_itemвременный (см. раздел 2.4.1). По завершении функции combine()никакого доступа к нему не будет. Фактически создается объект, удаляющийся после того, как его значение добавляется в объект item.
Чтобы предотвратить использование конструктора в контексте, который требует неявного преобразования, достаточно объявить его явным (explicit constructor) с использованием ключевого слова explicit:
class Sales_data {
public:
Sales_data() = default;
Sales_data(const std::string &s, unsigned n, double p):
bookNo(s), units_sold(n), revenue (p*n) { }
explicit Sales_data(const std::string &s): bookNo(s) { }
explicit Sales_data(std::istream&); // остальные члены, как прежде
};
Теперь ни один из конструкторов не применим для неявного создания объектов класса Sales_data. Ни один из предыдущих способов применения теперь не сработает:
item.combine(null_book); // ошибка: конструктор string теперь явный
item.combine(cin); // ошибка: конструктор istream теперь явный
Ключевое слово explicitимеет значение только для тех конструкторов, которые могут быть вызваны с одним аргументом. Конструкторы, требующие большего количества аргументов, не используются для неявного преобразования, поэтому нет никакой необходимости определять их как explicit. Ключевое слово explicitиспользуется только в объявлениях конструкторов в классе. В определении вне тела класса его не повторяют.
// ошибка: ключевое слово explicit допустимо только для
// объявлений конструкторов в заголовке класса
explicit Sales_data::Sales_data(istream& is) {
read(is, *this);
}
Одним из контекстов, в котором происходит неявное преобразования, является использование формы инициализации копированием (со знаком =) (см. раздел 3.2.1). С этой формой инициализации нельзя использовать явный конструктор; придется использовать прямую инициализацию:
Sales_data item1(null_book); // ok: прямая инициализация
// ошибка: с явным конструктором нельзя использовать форму
// инициализации копированием
Sales_data item2 = null_book;
Явный конструктор применим только с прямой формой инициализации (см. раздел 3.2.1). Кроме того, компилятор не будет использовать этот конструктор в автоматическом преобразовании.
Хотя компилятор не будет использовать явный конструктор для неявного преобразования, его можно использовать для преобразования явно:
// ok: аргумент - явно созданный объект класса Sales_data
item.combine(Sales_data(null_book));
// ok: static_cast может использовать явный конструктор
item.combine(static_cast(cin));
В первом вызове конструктор Sales_data()используется непосредственно. Этот вызов создает временный объект класса Sales_data, используя конструктор Sales_data(), получающий строку. Во втором вызове используется оператор static_cast(см. раздел 4.11.3) для выполнения явного, а не неявного преобразования. В этом вызове оператор static_castиспользует для создания временного объекта класса Sales_dataконструктор с параметром типа istream.
Интервал:
Закладка: