straustrup2 (852740), страница 46

Файл №852740 straustrup2 (Бьерн Страуструп. Язык программирования С++) 46 страницаstraustrup2 (852740) страница 462021-10-05СтудИзба
Просмтор этого файла доступен только зарегистрированным пользователям. Но у нас супер быстрая регистрация: достаточно только электронной почты!

Текст из файла (страница 46)

В большинстве случаев для этого не требуется особый стильпрограммирования, существенно отличающийся от того, который мы только что рассматривали. Простона производный класс возлагается некоторая дополнительная работа. Обычно она сводится кпереопределению одной или нескольких виртуальных функций (см. $$13.2 и $$8.7).

В некоторыхслучаях классы-братья должны иметь общую информацию. Поскольку С++ - язык со строгим контролемтипов, общность информации возможна только при явном указании того, что является общим в этихклассах. Способом такого указания может служить виртуальный базовый класс.Виртуальный базовый класс можно использовать для представления "головного" класса, который можетконкретизироваться разными способами:class window {// головная информацияvirtual void draw();};Для простоты рассмотрим только один вид общей информации из класса window - функцию draw().Можно определять разные более развитые классы, представляющие окна (window).

В каждомопределяется своя (более развитая) функция рисования (draw):class window_w_border : public virtual window {// класс "окно с рамкой"// определения, связанные с рамкойvoid draw();};167Бьерн Страуструп.Язык программирования С++class window_w_menu : public virtual window {// класс "окно с меню"// определения, связанные с менюvoid draw();};Теперь хотелось бы определить окно с рамкой и меню:class window_w_border_and_menu: public virtual window,public window_w_border,public window_w_menu {// класс "окно с рамкой и меню"void draw();};Каждый производный класс добавляет новые свойства окна. Чтобы воспользоваться комбинацией всехэтих свойств, мы должны гарантировать, что один и тот же объект класса window используется дляпредставления вхождений базового класса window в эти производные классы. Именно это обеспечиваетописание window во всех производных классах как виртуального базового класса.Можно следующим образом изобразить состав объекта класса window_w_border_and_menu:Чтобы увидеть разницу между обычным и виртуальным наследованием, сравните этот рисунок срисунком из $$6.5, показывающим состав объекта класса satellite.

В графе наследования каждыйбазовый класс с данным именем, который был указан как виртуальный, будет представленединственным объектом этого класса. Напротив, каждый базовый класс, который при описаниинаследования не был указан как виртуальный, будет представлен своим собственным объектом.Теперь надо написать все эти функции draw(). Это не слишком трудно, но для неосторожногопрограммиста здесь есть ловушка. Сначала пойдем самым простым путем, который как раз к ней иведет:void window_w_border::draw(){window::draw();// рисуем рамку}void window_w_menu::draw(){window::draw();// рисуем меню}Пока все хорошо.

Все это очевидно, и мы следуем образцу определения таких функций при условииединственного наследования ($$6.2.1), который работал прекрасно. Однако, в производном классеследующего уровня появляется ловушка:void window_w_border_and_menu::draw() // ловушка!{window_w_border::draw();window_w_menu::draw();// теперь операции, относящиеся только// к окну с рамкой и меню}На первый взгляд все вполне нормально. Как обычно, сначала выполняются все операции,необходимые для базовых классов, а затем те, которые относятся собственно к производным классам.Но в результате функция window::draw() будет вызываться дважды! Для большинства графическихпрограмм это не просто излишний вызов, а порча картинки на экране. Обычно вторая выдача на экранзатирает первую.Чтобы избежать ловушки, надо действовать не так поспешно.

Мы отделим действия, выполняемые168Бьерн Страуструп.Язык программирования С++базовым классом, от действий, выполняемых из базового класса. Для этого в каждом классе введемфункцию _draw(), которая выполняет нужные только для него действия, а функция draw() будетвыполнять те же действия плюс действия, нужные для каждого базового класса. Для класса windowизменения сводятся к введению излишней функции:class window {// головная информацияvoid _draw();void draw();};Для производных классов эффект тот же:class window_w_border : public virtual window {// класс "окно с рамкой"// определения, связанные с рамкойvoid _draw();void draw();};void window_w_border::draw(){window::_draw();_draw();// рисует рамку};Только для производного класса следующего уровня проявляется отличие функции, которое ипозволяет обойти ловушку с повторным вызовом window::draw(), поскольку теперь вызываетсяwindow::_draw() и только один раз:class window_w_border_and_menu: public virtual window,public window_w_border,public window_w_menu {void _draw();void draw();};void window_w_border_and_menu::draw(){window::_draw();window_w_border::_draw();window_w_menu::_draw();_draw();// теперь операции, относящиеся только// к окну с рамкой и меню}Не обязательно иметь обе функции window::draw() и window::_draw(), но наличие их позволяет избежатьразличных простых описок.В этом примере класс window служит хранилищем общей для window_w_border и window_w_menuинформации и определяет интерфейс для общения этих двух классов.

Если используетсяединственное наследование, то общность информации в дереве классов достигается тем, что этаинформация передвигается к корню дерева до тех пор, пока она не станет доступна всемзаинтересованным в ней узловым классам. В результате легко возникает неприятный эффект: кореньдерева или близкие к нему классы используются как пространство глобальных имен для всех классовдерева, а иерархия классов вырождается в множество несвязанных объектов.Существенно, чтобы в каждом из классов-братьев переопределялись функции, определенные в общемвиртуальном базовом классе. Таким образом каждый из братьев может получить свой вариантопераций, отличный от других.

Пусть в классе window есть общая функция ввода get_input():class window {169Бьерн Страуструп.Язык программирования С++// головная информацияvirtual void draw();virtual void get_input();};В одном из производных классов можно использовать эту функцию, не задумываясь о том, где онаопределена:class window_w_banner : public virtual window {// класс "окно с заголовком"void draw();void update_banner_text();};void window_w_banner::update_banner_text(){// ...get_input();// изменить текст заголовка}В другом производном классе функцию get_input() можно определять, не задумываясь о том, кто еебудет использовать:class window_w_menu : public virtual window {// класс "окно с меню"// определения, связанные с менюvoid draw();void get_input(); // переопределяет window::get_input()};Все эти определения собираются вместе в производном классе следующего уровня:class window_w_banner_and_menu: public virtual window,public window_w_banner,public window_w_menu{void draw();};Контроль неоднозначности позволяет убедиться, что в классах-братьях определены разные функции:class window_w_input : public virtual window {// ...void draw();void get_input(); // переопределяет window::get_input};class window_w_input_and_menu: public virtual window,public window_w_input,public window_w_menu{// ошибка: оба класса window_w_input и// window_w_menu переопределяют функцию// window::get_inputvoid draw();};Транслятор обнаруживает подобную ошибку, а устранить неоднозначность можно обычным способом:ввести в классы window_w_input и window_w_menu функцию, переопределяющую "функциюнарушителя", и каким-то образом устранить неоднозначность:class window_w_input_and_menu170Бьерн Страуструп.Язык программирования С++: public virtual window,public window_w_input,public window_w_menu{void draw();void get_input();};В этом классе window_w_input_and_menu::get_input() будет переопределять все функции get_input().Подробно механизм разрешения неоднозначности описан в $$R.10.1.1.6.6 Контроль доступаЧлен класса может быть частным (private), защищенным (protected) или общим (public):Частный член класса X могут использовать только функции-члены и друзья класса X.Защищенный член класса X могут использовать только функции-члены и друзья класса X, а так жефункции-члены и друзья всехпроизводных от X классов (см.

$$5.4.1).Общий член можно использовать в любой функции.Эти правила соответствуют делению обращающихся к классу функций на три вида: функции,реализующие класс (его друзья и члены), функции, реализующие производный класс (друзья и членыпроизводного класса) и все остальные функции.Контроль доступа применяется единообразно ко всем именам. На контроль доступа не влияет, какуюименно сущность обозначает имя. Это означает, что частными могут быть функции-члены, константы ит.д. наравне с частными членами, представляющими данные:class X {private:enum { A, B };void f(int);int a;};void X::f(int i){if (i<A) f(i+B);a++;}void g(X& x){int i = X::A;x.f(2);x.a++;}// ошибка: X::A частный член// ошибка: X::f частный член// ошибка: X::a частный член6.6.1 Защищенные членыДадим пример защищенных членов, вернувшись к классу window из предыдущего раздела. Здесьфункции _draw() предназначались только для использования в производных классах, посколькупредоставляли неполный набор возможностей, а поэтому не были достаточны удобны и надежны дляобщего применения.

Характеристики

Тип файла
PDF-файл
Размер
2,87 Mb
Тип материала
Высшее учебное заведение

Список файлов книги

Свежие статьи
Популярно сейчас
Почему делать на заказ в разы дороже, чем купить готовую учебную работу на СтудИзбе? Наши учебные работы продаются каждый год, тогда как большинство заказов выполняются с нуля. Найдите подходящий учебный материал на СтудИзбе!
Ответы на популярные вопросы
Да! Наши авторы собирают и выкладывают те работы, которые сдаются в Вашем учебном заведении ежегодно и уже проверены преподавателями.
Да! У нас любой человек может выложить любую учебную работу и зарабатывать на её продажах! Но каждый учебный материал публикуется только после тщательной проверки администрацией.
Вернём деньги! А если быть более точными, то автору даётся немного времени на исправление, а если не исправит или выйдет время, то вернём деньги в полном объёме!
Да! На равне с готовыми студенческими работами у нас продаются услуги. Цены на услуги видны сразу, то есть Вам нужно только указать параметры и сразу можно оплачивать.
Отзывы студентов
Ставлю 10/10
Все нравится, очень удобный сайт, помогает в учебе. Кроме этого, можно заработать самому, выставляя готовые учебные материалы на продажу здесь. Рейтинги и отзывы на преподавателей очень помогают сориентироваться в начале нового семестра. Спасибо за такую функцию. Ставлю максимальную оценку.
Лучшая платформа для успешной сдачи сессии
Познакомился со СтудИзбой благодаря своему другу, очень нравится интерфейс, количество доступных файлов, цена, в общем, все прекрасно. Даже сам продаю какие-то свои работы.
Студизба ван лав ❤
Очень офигенный сайт для студентов. Много полезных учебных материалов. Пользуюсь студизбой с октября 2021 года. Серьёзных нареканий нет. Хотелось бы, что бы ввели подписочную модель и сделали материалы дешевле 300 рублей в рамках подписки бесплатными.
Отличный сайт
Лично меня всё устраивает - и покупка, и продажа; и цены, и возможность предпросмотра куска файла, и обилие бесплатных файлов (в подборках по авторам, читай, ВУЗам и факультетам). Есть определённые баги, но всё решаемо, да и администраторы реагируют в течение суток.
Маленький отзыв о большом помощнике!
Студизба спасает в те моменты, когда сроки горят, а работ накопилось достаточно. Довольно удобный сайт с простой навигацией и огромным количеством материалов.
Студ. Изба как крупнейший сборник работ для студентов
Тут дофига бывает всего полезного. Печально, что бывают предметы по которым даже одного бесплатного решения нет, но это скорее вопрос к студентам. В остальном всё здорово.
Спасательный островок
Если уже не успеваешь разобраться или застрял на каком-то задание поможет тебе быстро и недорого решить твою проблему.
Всё и так отлично
Всё очень удобно. Особенно круто, что есть система бонусов и можно выводить остатки денег. Очень много качественных бесплатных файлов.
Отзыв о системе "Студизба"
Отличная платформа для распространения работ, востребованных студентами. Хорошо налаженная и качественная работа сайта, огромная база заданий и аудитория.
Отличный помощник
Отличный сайт с кучей полезных файлов, позволяющий найти много методичек / учебников / отзывов о вузах и преподователях.
Отлично помогает студентам в любой момент для решения трудных и незамедлительных задач
Хотелось бы больше конкретной информации о преподавателях. А так в принципе хороший сайт, всегда им пользуюсь и ни разу не было желания прекратить. Хороший сайт для помощи студентам, удобный и приятный интерфейс. Из недостатков можно выделить только отсутствия небольшого количества файлов.
Спасибо за шикарный сайт
Великолепный сайт на котором студент за не большие деньги может найти помощь с дз, проектами курсовыми, лабораторными, а также узнать отзывы на преподавателей и бесплатно скачать пособия.
Популярные преподаватели
Добавляйте материалы
и зарабатывайте!
Продажи идут автоматически
6549
Авторов
на СтудИзбе
299
Средний доход
с одного платного файла
Обучение Подробнее