Стенли Липпман - Язык программирования C++. Пятое издание
- Название:Язык программирования C++. Пятое издание
- Автор:
- Жанр:
- Издательство:Издательский дом Вильямс
- Год:2014
- Город:Москва
- ISBN:978-5-8459-1839-0
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Стенли Липпман - Язык программирования C++. Пятое издание краткое содержание
Вы держите в руках новое издание популярного и исчерпывающего бестселлера по языку программирования С++, которое было полностью пересмотрено и обновлено под
. Оно поможет вам быстро изучить язык и использовать его весьма эффективными и передовыми способами. В соответствии с самыми передовыми и современными методиками изложения материала авторы демонстрируют использование базового языка и его стандартной библиотеки для разработки эффективного, читабельного и мощного кода.
С самого начала этой книги читатель знакомится со стандартной библиотекой С++, ее самыми популярными функциями и средствами, что позволяет сразу же приступить к написанию полезных программ, еще не овладев всеми нюансами языка. Большинство примеров из книги было пересмотрено так, чтобы использовать новые средства языка и продемонстрировать их наилучшие способы применения. Эта книга — не только проверенное руководство для новичков в С++, она содержит также авторитетное обсуждение базовых концепций и методик языка С++ и является ценным ресурсом для опытных программистов, особенно желающих побыстрей узнать об усовершенствованиях С++11.
Стенли Б. Липпман Жози Лажойе Барбара Э. Му • Узнайте, как использовать новые средства языка С++11 и стандартной библиотеки для быстрого создания надежных программ, а также ознакомьтесь с высокоуровневым программированием
• Учитесь на примерах, в которых показаны передовые стили программирования и методики проектирования
• Изучите принципы и узнайте почему язык С++11 работает именно так
• Воспользуйтесь множеством перекрестных ссылок, способных помочь вам объединить взаимосвязанные концепции и проникнуть в суть
• Ознакомьтесь с современными методиками обучения и извлеките пользу из упражнений, в которых подчеркиваются ключевые моменты, позволяющие избежать проблем
• Освойте лучшие методики программирования и закрепите на практике изученный материал
Исходный код примеров можно загрузить с веб-страницы книги на сайте издательства по адресу: http://www.williamspublishing.com
Язык программирования C++. Пятое издание - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
Когда у класса есть несколько базовых классов, производный класс вполне может унаследовать одноименный член от двух и более своих базовых классов. При использовании этого имени без уточнения класса происходит неоднозначность.
Например, если классы ZooAnimal
и Endangered
определяют функцию-член max_weight()
, а класс Panda
не определяет ее, то следующий вызов ошибочен:
double d = ying_yang.max_weight();
В результате наследования класс Panda
получает две функции-члена max_weight()
, что совершенно допустимо. Наследование создает потенциальную неоднозначность. Ее вполне можно избежать, если объект Panda
не будет вызывать функцию-член max_weight()
. Ошибки также можно избежать, если явно указать требуемую версию функции: ZooAnimal::max_weight()
или Endangered::max_weight()
. Ошибка неоднозначности произойдет только при попытке использования функции без уточнения.
Неоднозначность двойного наследования функции-члена max_weight
вполне очевидна и логична. Удивительно узнать то, что ошибка произошла бы, даже если у двух наследованных функций были разные списки параметров. Точно так же эта ошибка произошла бы даже в случае, если бы функция max_weight()
была закрытой в одном классе и открытой или защищенной в другом. И наконец, если бы функция max_weight()
была определена в классе Bear
, а не в классе ZooAnimal
, то вызов все равно был бы ошибочен.
Как обычно, поиск имени осуществляется под контролем соответствия типов (см. раздел 6.4.1). Когда компилятор находит имя функции max_weight()
в двух разных областях видимости, он оповещает об ошибке неоднозначности.
Проще всего избежать потенциальных неоднозначностей, определив версию такой функции в производном классе. Например, снабдив класс Panda
функцией max_weight()
, можно решить все проблемы:
double Panda::max_weight() const {
return std::max(ZooAnimal::max_weight(),
Endangered::max_weight());
}
Упражнение 18.26. С учетом иерархии кода для упражнений объясните, почему ошибочен следующий вызов функции print()
? Исправьте структуру MI
так, чтобы позволить этот вызов.
MI mi;
mi.print(42);
Упражнение 18.27. С учетом иерархии кода для упражнений и того, что в структуру MI
добавлена приведенная ниже функция foo()
, ответьте на следующие вопросы:
int ival;
double dval;
void MI::foo(double cval) {
int dval;
// варианты вопросов упражнения располагаются здесь ...
}
(a) Перечислите все имена, видимые из функции MI::foo()
.
(b) Видимы ли какие-нибудь имена из больше чем одного базового класса?
(c) Присвойте локальному экземпляру переменной dval
сумму переменных-членов dval
объектов классов Base1
и Derived
.
(d) Присвойте значение последнего элемента вектора MI::dvec
переменной-члену Base2::fval
.
(e) Присвойте переменной-члену cval
класса Base1
первый символ строки sval
класса Derived
.
struct Base1 {
void print(int) const; // по умолчанию открыты
protected:
int ival;
double dval;
char cval;
private:
int *id;
};
struct Base2 {
void print(double) const; // по умолчанию открыты
protected:
double fval;
private:
double dval;
};
struct Derived : public Base1 {
void print(std::string) const; // по умолчанию открыты
protected:
std::string sval;
double dval;
};
struct MI : public Derived, public Base2 {
void print(std::vector); // по умолчанию открыты
protected:
int *ival;
std::vector dvec;
};
18.3.4. Виртуальное наследование
Хотя список наследования класса не может включать тот же базовый класс несколько раз, класс вполне может унаследовать тот же базовый класс многократно. Тот же базовый класс может быть унаследован косвенно, от двух его собственных прямых базовых классов, либо он может унаследовать некий класс и прямо, и косвенно, через другой из его базовых классов.
Например, библиотечные классы ввода-вывода istream
и ostream
происходят от общего абстрактного базового класса basic_ios
. Этот класс содержит буфер потока и управляет флагом состояния потока. Класс iostream
, способный и читать, и писать в поток, происходит непосредственно и от класса istream
, и от класса ostream
. Поскольку оба класса происходят от класса basic_ios
, класс iostream
наследует этот базовый класс дважды: один раз от класса istream
и один раз от класса ostream
.
По умолчанию объект производного класса содержит отдельные части, соответствующие каждому классу в его цепи наследования. Если тот же базовый класс наследуется несколько раз, то у объекта производного класса будет больше одного внутреннего объекта этого типа.
Для такого класса, как iostream
, это стандартное поведение не работает. Объект класса iostream
должен использовать тот же буфер и для чтения, и для записи, а его флаг должен отражать состояние операций и ввода, и вывода. Если у объекта класса iostream
будут две копии объекта класса basic_ios
, то их совместное использование невозможно.
В языке С++ для решения этой проблемы используется виртуальное наследование (virtual inheritance). Виртуальное наследование позволяет классу указать, что его базовый класс будет использоваться совместно. Совместно используемый внутренний объект базового класса называется виртуальным базовым классом (virtual base class). Независимо от того, сколько раз тот же базовый виртуальный класс присутствует в иерархии наследования, объект производного класса содержит только один совместно используемый внутренний объект этого виртуального базового класса.
Panda
В прошлом велись дебаты о принадлежности вида панда к семейству енотов или медведей. Чтобы отобразить эти сомнения, изменим класс Panda
так, чтобы он происходил и от класса Bear
, и от класса Raccoon
. Чтобы избавить класс Panda
от двух частей базового класса ZooAnimal
, определим наследование классов Bear
и Raccoon
от класса ZooAnimal
как виртуальное. Новая иерархия представлена на рис. 18.3.

Рис. 18.3. Виртуальное наследование в иерархии класса Panda
Глядя на новую иерархию, можно заметить неочевидный аспект виртуального наследования. Виртуальное наследование должно быть осуществлено прежде, чем в нем возникнет потребность. Например, в этих классах потребность в виртуальном наследовании возникает только при определении класса Panda
. Но если бы классы Bear
и Raccoon
не определили бы свое происхождение от класса ZooAnimal
как виртуальное, конструкция класса Panda
была бы неудачна.
Интервал:
Закладка: