Стенли Липпман - Язык программирования C++. Пятое издание
- Название:Язык программирования C++. Пятое издание
- Автор:
- Жанр:
- Издательство:Издательский дом Вильямс
- Год:2014
- Город:Москва
- ISBN:978-5-8459-1839-0
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Стенли Липпман - Язык программирования C++. Пятое издание краткое содержание
Вы держите в руках новое издание популярного и исчерпывающего бестселлера по языку программирования С++, которое было полностью пересмотрено и обновлено под
. Оно поможет вам быстро изучить язык и использовать его весьма эффективными и передовыми способами. В соответствии с самыми передовыми и современными методиками изложения материала авторы демонстрируют использование базового языка и его стандартной библиотеки для разработки эффективного, читабельного и мощного кода.
С самого начала этой книги читатель знакомится со стандартной библиотекой С++, ее самыми популярными функциями и средствами, что позволяет сразу же приступить к написанию полезных программ, еще не овладев всеми нюансами языка. Большинство примеров из книги было пересмотрено так, чтобы использовать новые средства языка и продемонстрировать их наилучшие способы применения. Эта книга — не только проверенное руководство для новичков в С++, она содержит также авторитетное обсуждение базовых концепций и методик языка С++ и является ценным ресурсом для опытных программистов, особенно желающих побыстрей узнать об усовершенствованиях С++11.
Стенли Б. Липпман Жози Лажойе Барбара Э. Му • Узнайте, как использовать новые средства языка С++11 и стандартной библиотеки для быстрого создания надежных программ, а также ознакомьтесь с высокоуровневым программированием
• Учитесь на примерах, в которых показаны передовые стили программирования и методики проектирования
• Изучите принципы и узнайте почему язык С++11 работает именно так
• Воспользуйтесь множеством перекрестных ссылок, способных помочь вам объединить взаимосвязанные концепции и проникнуть в суть
• Ознакомьтесь с современными методиками обучения и извлеките пользу из упражнений, в которых подчеркиваются ключевые моменты, позволяющие избежать проблем
• Освойте лучшие методики программирования и закрепите на практике изученный материал
Исходный код примеров можно загрузить с веб-страницы книги на сайте издательства по адресу: http://www.williamspublishing.com
Язык программирования C++. Пятое издание - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
Тот факт, что область видимости производного класса вложена в область видимости его базовых классов, может быть удивителен. В конце концов, базовые и производные классы определяются в разных частях текста программы. Но именно это иерархическое вложение областей видимости класса позволяет членам производного класса использовать члены его базового класса, как будто они являются частью производного класса. Рассмотрим пример:
Bulk_quote bulk;
cout << bulk.isbn();
В этом коде поиск определения имени isbn()
осуществляется следующим образом.
• Поскольку вызывается функция isbn()
объекта типа Bulk_quote
, поиск начинается в классе Bulk_quote
. В этом классе имя isbn()
не найдено.
• Поскольку класс Bulk_quote
происходит от класса Disc_quote
, в нем и продолжается поиск. Имя все еще не найдено.
• Поскольку класс Disc_quote
происходит от класса Quote
, поиск продолжается в нем. В этом классе находится определение имени isbn()
; таким образом, вызов isbn()
распознается как вызов функции isbn()
класса Quote
.
Статический тип (см. раздел 15.2.3) объекта, ссылки или указателя определяет, какие члены этого объекта будут видимы. Даже когда статический и динамический типы отличаются (это бывает в случае, когда используется ссылка или указатель на базовый класс), именно статический тип определяет применимые члены. Например, в класс Disc_quote
можно было бы добавить функцию-член, которая возвращает пару (тип pair
) (см. раздел 11.2.3), содержащую минимальное (или максимальное) количество и цену со скидкой.
class Disc_quote : public Quote {
public:
std::pair discount_policy() const
{ return {quantity, discount}; }
// другие члены как прежде
};
Функцию discount_policy()
можно использовать только через объект, указатель, или ссылку на тип Disc_quote
, или класс, производный от него:
Bulk_quote bulk;
Bulk_quote *bulkP = &bulk; // статический и динамический типы совпадают
Quote *itemP = &bulk; // статический и динамический типы отличаются
bulkP->discount_policy(); // ok: bulkP имеет тип Bulk_quote*
itemP->discount_policy(); // ошибка: itemP имеет тип Quote*
Хотя объект bulk
имеет функцию-член discount_policy()
, она недоступна через указатель itemP
. Тип itemP
— указатель на тип Quote
, а это значит, что поиск имени discount_policy()
начнется в классе Quote
. У класса Quote
нет члена по имени discount_policy()
, поэтому вызов этой функции-члена объекта, ссылки или указателя на тип Quote
невозможен.
Как и любая другая, область видимости производного класса позволяет повторно использовать имя, определенное в его прямом или косвенном базовом классе. Как обычно, имена, определенные во внутренней области видимости (например, в производном классе), скрывают имена во внешней области видимости (например, в базовом классе) (см. раздел 2.2.4):
struct Base {
Base() : mem(0) { }
protected:
int mem;
};
struct Derived : Base {
Derived(int i): mem(i) { } // Derived::mem инициализируется i
// Base::mem инициализируется по умолчанию
int get_mem() { return mem; } // возвращает Derived::mem
protected:
int mem; // скрывает mem в Base
};
Ссылка на переменную mem
в функции get_mem()
распознается как имя в классе Derived
. Таким образом, код
Derived d(42);
cout << d.get_mem() << endl; // выводит 42
выведет значение 42
.
Член производного класса, имя которого совпадает с именем члена базового класса, скрывает член базового класса и предотвращает прямой доступ к нему.
Для доступа к скрытому члену базового класса можно использовать оператор области видимости.
struct Derived : Base {
int get_base_mem() { return Base::mem; }
};
Оператор области видимости изменяет нормальный порядок поиска и заставляет компилятор начинать поиск имени mem
с класса Base
. Если бы код выше был выполнен с этой версией класса Derived
, то результатом вызова d.get_mem()
был бы 0
.
Кроме переопределения унаследованных виртуальных функций, производный класс обычно не должен повторно использовать имена, определенные в его базовом классе.
Для понимания наследования в языке С++ крайне важно знать, как распознаются вызовы функций. Процесс распознавания вызова p->mem()
(или obj.mem()
) проходит в четыре этапа.
• Сначала определяется статический тип объекта p
(или obj
). Поскольку это вызов члена класса, тип будет классом.
• Поиск имени mem
осуществляется в классе, который соответствует статическому типу объекта p
(или obj
). Если функция mem()
не найдена, поиск продолжается в прямом базовом классе и далее по цепи классов, пока имя mem
не будет найдено или пока не будет осмотрен последний класс. Если функция mem()
не будет найдена ни в самом классе, ни в его базовых классах, вызов откомпилирован не будет.
• Как только имя mem
будет найдено, осуществляется обычная проверка соответствия типов (см. раздел 6.1), гарантирующая допустимость найденного определения для данного вызова.
• Если вызов допустим, компилятор создает код, зависящий от того, является ли вызываемая функция виртуальной или нет:
- Если функция mem()
виртуальная и вызов осуществляется через ссылку или указатель, то компилятор создает код, который во время выполнения определяет на основании динамического типа объекта выполняемую версию функции.
- В противном случае, если функция не является виртуальной или если вызов осуществляется для объекта (а не ссылки или указателя), то компилятор создает код обычного вызова функции.
Как уже упоминалось, функции, объявленные во внутренней области видимости, не перегружают функции, объявленные во внешней области видимости (см. раздел 6.4.1). В результате функции, определенные в производном классе, не перегружают функции-члены, определенные в его базовом классе (классах). Подобно любой другой области видимости, если имя члена производного класса (т.е. определенное во внутренней области видимости) совпадает с именем члена базового класса (т.е. именем во внешней области видимости), то в рамках производного класса имя, определенное в производном классе, скрывает имя в базовом классе. Имя функции-члена базового класса скрывается, даже если у функций будут разные списки параметров:
Читать дальшеИнтервал:
Закладка: