Стенли Липпман - Язык программирования C++. Пятое издание
- Название:Язык программирования C++. Пятое издание
- Автор:
- Жанр:
- Издательство:Издательский дом Вильямс
- Год:2014
- Город:Москва
- ISBN:978-5-8459-1839-0
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Стенли Липпман - Язык программирования C++. Пятое издание краткое содержание
Вы держите в руках новое издание популярного и исчерпывающего бестселлера по языку программирования С++, которое было полностью пересмотрено и обновлено под
. Оно поможет вам быстро изучить язык и использовать его весьма эффективными и передовыми способами. В соответствии с самыми передовыми и современными методиками изложения материала авторы демонстрируют использование базового языка и его стандартной библиотеки для разработки эффективного, читабельного и мощного кода.
С самого начала этой книги читатель знакомится со стандартной библиотекой С++, ее самыми популярными функциями и средствами, что позволяет сразу же приступить к написанию полезных программ, еще не овладев всеми нюансами языка. Большинство примеров из книги было пересмотрено так, чтобы использовать новые средства языка и продемонстрировать их наилучшие способы применения. Эта книга — не только проверенное руководство для новичков в С++, она содержит также авторитетное обсуждение базовых концепций и методик языка С++ и является ценным ресурсом для опытных программистов, особенно желающих побыстрей узнать об усовершенствованиях С++11.
Стенли Б. Липпман Жози Лажойе Барбара Э. Му • Узнайте, как использовать новые средства языка С++11 и стандартной библиотеки для быстрого создания надежных программ, а также ознакомьтесь с высокоуровневым программированием
• Учитесь на примерах, в которых показаны передовые стили программирования и методики проектирования
• Изучите принципы и узнайте почему язык С++11 работает именно так
• Воспользуйтесь множеством перекрестных ссылок, способных помочь вам объединить взаимосвязанные концепции и проникнуть в суть
• Ознакомьтесь с современными методиками обучения и извлеките пользу из упражнений, в которых подчеркиваются ключевые моменты, позволяющие избежать проблем
• Освойте лучшие методики программирования и закрепите на практике изученный материал
Исходный код примеров можно загрузить с веб-страницы книги на сайте издательства по адресу: http://www.williamspublishing.com
Язык программирования C++. Пятое издание - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
15.7.4. Унаследованные конструкторы
По новому стандарту производный класс может многократно использовать конструкторы, определенные его прямым базовым классом. Хотя, как будет продемонстрировано далее, такие конструкторы не наследуются в обычном смысле этого слова, о них, тем не менее, говорят как об унаследованных. По тем же причинам, по которым класс может инициализировать только свой прямой базовый класс, класс может наследовать конструкторы только от своего прямого базового класса. Класс не может унаследовать стандартный конструктор, конструктор копий и перемещения. Если производный класс не определяет эти конструкторы сам, то компилятор синтезирует их, как обычно.
Производный класс наследует конструкторы своего базового класса при помощи объявления using
, в котором указан его (прямой) базовый класс. В качестве примера можно переопределить класс Bulk_quote
(см. раздел 15.4) так, чтобы он унаследовал конструкторы от класса Disc_quote:
class Bulk_quote : public Disc_quote {
public:
using Disc_quote::Disc_quote; // наследует конструкторы Disc_quote
double net_price(std::size_t) const;
};
Обычно объявление using
просто делает имя видимым в текущей области видимости. Применительно к конструктору объявление using
приводит к созданию компилятором кода. Компилятор создает в производном классе конструктор, соответствующий каждому конструктору в базовом классе. Таким образом, для каждого конструктора в базовом классе компилятор создает в производном классе конструктор с таким же списком параметров.
Эти созданные компилятором конструкторы имеют такую форму:
производный ( параметры ) : базовый ( аргументы ) { }
где производный
— имя производного класса; базовый
— имя базового класса; параметры
— список параметров конструктора; аргументы
передают параметры из конструктора производного класса в конструктор базового. В классе Bulk_quote
унаследованный конструктор был бы эквивалентен следующему:
Bulk_quote(const std::string& book, double price,
std::size_t qty, double disc):
Disc_quote(book, price, qty, disc) { }
Если у производного класса есть какие-нибудь собственные переменные-члены, они инициализируются по умолчанию (см. раздел 7.1.4).
В отличие от объявлений using
для обычных членов, объявление using
для конструктора не изменяет уровень доступа унаследованного конструктора (конструкторов). Например, независимо от того, где расположено объявление using
, закрытый конструктор в базовом классе остается закрытым в производном; то же относится к защищенным и открытым конструкторам.
Кроме того, объявление using
не может использовать определение как explicit
или constexpr
. Если конструктор объявлен как explicit
(см. раздел 7.5.4) или constexpr
(см. раздел 7.5.6) в базовом классе, у унаследованного конструктора будет то же свойство.
Если у конструктора базового класса есть аргументы по умолчанию (см. раздел 6.5.1), они не наследуются. Вместо этого производный класс получает несколько унаследованных конструкторов, в которых каждый параметр с аргументом по умолчанию благополучно пропущен. Например, если у базового класса будет конструктор с двумя параметрами, у второго из которых будет аргумент по умолчанию, то производный класс получит два конструктора: один с обоими параметрами (и никакого аргумента по умолчанию) и второй конструктор с одним параметром, соответствующим левому параметру без аргумента по умолчанию в базовом классе.
Если у базового класса есть несколько конструкторов, то за двумя исключениями производный класс унаследует каждый из конструкторов своего базового класса. Первое исключение — производный класс может унаследовать некоторые конструкторы и определить собственные версии других конструкторов. Если производный класс определяет конструктор с теми же параметрами, что и конструктор в базовом классе, то этот конструктор не наследуется. Конструктор, определенный в производном классе, используется вместо унаследованного конструктора.
Второе исключение — стандартный конструктор, конструктор копий и конструктор перемещения не наследуются. Эти конструкторы синтезируются с использованием обычных правил. Унаследованный конструктор не рассматривается как пользовательский конструктор. Поэтому у класса, который содержит только унаследованные конструкторы, будет синтезируемый стандартный конструктор.
Упражнение 15.27. Переопределите свой класс Bulk_quote
так, чтобы унаследовать его конструкторы.
15.8. Контейнеры и наследование
При использовании контейнера для хранения объектов из иерархии наследования их обычно хранят косвенно. Нельзя поместить объекты связанных наследованием типов непосредственно в контейнер, поскольку нет никакого способа определить контейнер, содержащий элементы разных типов.
В качестве примера определим вектор, содержащий несколько объектов для книг, которые клиент желает купать. Вполне очевидно, что не получится использовать вектор, содержащий объекты класса Bulk_quote
. Нельзя преобразовать объекты класса Quote
в объекты класса Bulk_quote
(см. раздел 15.2.3), поэтому объекты класса Quote
в этот вектор поместить не получится.
Может быть и не так очевидно, но вектор объектов типа Quote
также нельзя использовать. В данном случае можно поместить объекты класса Bulk_quote
в контейнер, но эти объекты перестанут быть объектами класса Bulk_quote
:
vector basket;
basket.push_back(Quote("0-2 01-82 4 7 0-1", 50));
// ok, но в basket копируется только часть Quote объекта
basket.push_back(Bulk_quote("0-201-54848-8", 50, 10, .25));
// вызов версии, определенной в Quote, выводит 750, т.е. 15 * $50
cout << basket.back().net_price(15) << endl;
Элементами вектора basket
являются объекты класса Quote
. Когда в вектор добавляется объект класса Bulk_quote
, его производная часть игнорируется (см. раздел 15.2.3).
Поскольку при присвоении объекту базового класса объект производного класса усекается, контейнеры не очень удобны для хранения объектов разных классов, связанных наследственными отношениями.
Когда необходим контейнер, содержащий объекты, связанные наследованием, как правило, определяют контейнер указателей (предпочтительно интеллектуальных (см. раздел 12.1)) на базовый класс. Как обычно, динамический тип объекта, на который указывает этот указатель, мог бы быть типом базового класса или типом, производным от него:
Читать дальшеИнтервал:
Закладка: