Стенли Липпман - Язык программирования C++. Пятое издание
- Название:Язык программирования C++. Пятое издание
- Автор:
- Жанр:
- Издательство:Издательский дом Вильямс
- Год:2014
- Город:Москва
- ISBN:978-5-8459-1839-0
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Стенли Липпман - Язык программирования C++. Пятое издание краткое содержание
Вы держите в руках новое издание популярного и исчерпывающего бестселлера по языку программирования С++, которое было полностью пересмотрено и обновлено под
. Оно поможет вам быстро изучить язык и использовать его весьма эффективными и передовыми способами. В соответствии с самыми передовыми и современными методиками изложения материала авторы демонстрируют использование базового языка и его стандартной библиотеки для разработки эффективного, читабельного и мощного кода.
С самого начала этой книги читатель знакомится со стандартной библиотекой С++, ее самыми популярными функциями и средствами, что позволяет сразу же приступить к написанию полезных программ, еще не овладев всеми нюансами языка. Большинство примеров из книги было пересмотрено так, чтобы использовать новые средства языка и продемонстрировать их наилучшие способы применения. Эта книга — не только проверенное руководство для новичков в С++, она содержит также авторитетное обсуждение базовых концепций и методик языка С++ и является ценным ресурсом для опытных программистов, особенно желающих побыстрей узнать об усовершенствованиях С++11.
Стенли Б. Липпман Жози Лажойе Барбара Э. Му • Узнайте, как использовать новые средства языка С++11 и стандартной библиотеки для быстрого создания надежных программ, а также ознакомьтесь с высокоуровневым программированием
• Учитесь на примерах, в которых показаны передовые стили программирования и методики проектирования
• Изучите принципы и узнайте почему язык С++11 работает именно так
• Воспользуйтесь множеством перекрестных ссылок, способных помочь вам объединить взаимосвязанные концепции и проникнуть в суть
• Ознакомьтесь с современными методиками обучения и извлеките пользу из упражнений, в которых подчеркиваются ключевые моменты, позволяющие избежать проблем
• Освойте лучшие методики программирования и закрепите на практике изученный материал
Исходный код примеров можно загрузить с веб-страницы книги на сайте издательства по адресу: http://www.williamspublishing.com
Язык программирования C++. Пятое издание - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
Как обычно, при определении члена класса вне его тела следует указать, к какому классу он принадлежит. Так же, как обычно, имя созданного из шаблона класса включает его аргументы шаблона. При определении члена аргументы шаблона совпадают с параметрами шаблона. Таким образом, для функции-члена класса StrBlob
, определенной следующим образом:
тип_возвращаемого_значения StrBlob:: имя_члена ( список_парам )
соответствующий член шаблона Blob
будет выглядеть так:
template
тип_возвращаемого_значения Blob<���Т>:: имя_члена ( список_парам )
check()
и функции доступа к членамНачнем с определения функции-члена check()
, проверяющей предоставленный индекс:
template
void Blob::check(size_type i, const std::string &msg) const {
if (i >= data->size())
throw std::out_of_range(msg);
}
Кроме отличия в имени класса и использовании списка параметров шаблона, эта функция идентична первоначальной функции-члену класса StrBlob
.
Оператор индексирования и функция back()
используют параметр шаблона для определения типа возвращаемого значения, но в остальном они неизменны:
template
Т& Blob::back() {
check(0, "back on empty Blob");
return data->back();
}
template
T& Blob::operator[](size_type i) {
// если i слишком велико, check() передаст сообщение и предотвратит
// доступ к несуществующему элементу
check(i, "subscript out of range");
return (*data)[i];
}
В первоначальном классе StrBlob
эти операторы возвращали тип string&
. Шаблонная версия возвращает ссылку на любой тип, использованный при создании экземпляра шаблона Blob
.
Функция pop_back()
почти идентична оригинальной функции-члену класса StrBlob
:
template void Blob::pop_back() {
check(0, "pop_back on empty Blob");
data->pop_back();
}
Оператор индексирования и функция-член back()
перегружены как const
. Оставим определение этих функций-членов и функции front()
читателю в качестве самостоятельного упражнения.
Blob()
Подобно любым другим функциям-членам, определенным вне шаблона класса, конструктор начинается с объявления параметров шаблона для шаблона класса, членом которого он является:
template
Blob::Blob(): data(std::make_shared>()) { }
Здесь функция-член Blob()
определяется в пределах шаблона Blob
. Как и стандартный конструктор StrBlob()
(см. раздел 12.1.1), данный конструктор резервирует пустой вектор и сохраняет указатель на него в переменной data
. Как уже упоминалось, в качестве аргумента резервируемого шаблона vector
используется собственный параметр типа класса.
Точно так же конструктор, получающий параметр типа initializer_list
, использует свой параметр типа T
как тип элемента для своего параметра типа initializer_list
:
template
Blob::Blob(std::initializer_list il):
data(std::make_shared>(il)) { }
Подобно стандартному конструктору, этот конструктор резервирует новый вектор. В данном случае этот вектор инициализируется из параметра il
.
Чтобы использовать этот конструктор, следует передать список инициализации, тип элементов которого совместим с типом элемента Blob
:
Blob articles = {"a", "an", "the"};
Параметр этого конструктора имеет тип initializer_list
. Каждый строковый литерал в списке неявно преобразуется в тип string
.
По умолчанию экземпляр функции-члена шаблона класса создается, только если программа использует эту функцию-член. Рассмотрим следующий код:
// создает экземпляр Blob и конструктор initializer_list
Blob squares = {0,1,2,3,4,5,6,7,8,9};
// создает экземпляр Blob::size() const
for (size_t i = 0; i != squares.size(); ++i)
squares[i] = i*i; // создает экземпляр Blob::operator[](size_t)
Этот код создает экземпляр класса Blob
и трех его функций-членов: operator[]()
, size()
и конструктора initializer_list()
.
Если функция-член не используется, ее экземпляр не создается. Благодаря этому факту можно создавать экземпляры класса, используя типы, которые не отвечают требованиям для некоторых из операций шаблона (см. раздел 9.2).
По умолчанию экземпляр члена шаблона класса создается, только если он используется.
Из правила, согласно которому следует предоставить аргументы шаблона при использовании шаблона класса, есть одно исключение. В области видимости самого шаблона класса имя шаблона можно использовать без аргументов:
// BlobPtr передает исключение при попытке доступа к несуществующему
// элементу
template class BlobPtr
public:
BlobPtr(): curr(0) { }
BlobPtr(Blob &a, size_t sz = 0):
wptr(a.data), curr(sz) { } T& operator*() const {
auto p = check{curr, "dereference past end");
return (*p)[curr]; // (*p) - вектор, на который указывает этот
// объект
}
// инкремент и декремент
BlobPtr& operator++(); // префиксные операторы
BlobPtr& operator--();
private:
// если проверка успешна, check() возвращает shared_ptr на вектор
std::shared_ptr>
check(std::size_t, const std::string&) const;
// хранит weak_ptr, а значит, базовый вектор может быть удален
std::weak_ptr> wptr;
std::size_t curr; // текущая позиция в пределах массива
};
Внимательные читатели, вероятно, обратили внимание на то, что префиксные функции-члены инкремента и декремента шаблона класса BlobPtr
возвращают тип BlobPtr&
, а не BlobPtr&
. В области видимости шаблона класса компилятор рассматривает ссылки на сам шаблон так, как будто были подставлены аргументы шаблона, соответствующие собственным параметрам. Таким образом, этот код эквивалентен следующему:
BlobPtr& operator++();
BlobPtr& operator--();
При определении функций-членов вне тела шаблона класса следует помнить, что код находится не в области видимости класса, пока не встретилось имя класса (см. раздел 7.4):
// постфикс: осуществляет инкремент/декремент объекта, но возвращает
// неизменное значение
template
BlobPtr BlobPtr::operator++(int) {
// никакой проверки здесь не нужно; ее выполнит вызов префиксного
// инкремента
BlobPtr ret = *this; // сохранить текущее значение
++*this; // перемещение на один элемент; префиксный ++
// проверяет инкремент
Интервал:
Закладка: