Главная » Просмотр файлов » Б. Страуструп - Язык программирования С++

Б. Страуструп - Язык программирования С++ (1119446), страница 48

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

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

Однако, в производном классеследующего уровня появляется ловушка: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() предназначались только для использования в производных классах, посколькупредоставляли неполный набор возможностей, а поэтому не были достаточны удобны и надежны дляобщего применения. Они были как бы строительным материалом для более развитых функций. Сдругой стороны, функции draw() предназначались для общего применения. Это различие можновыразить, разбив интерфейсы классов window на две части - защищенный интерфейс и общийинтерфейс:171Бьерн Страуструп.Язык программирования С++class window {public:virtual void draw();// ...protected:void _draw();// другие функции, служащие строительным материаломprivate:// представление класса};Такое разбиение можно проводить и в производных классах, таких, как window_w_border илиwindow_w_menu.Префикс _ используется в именах защищенных функций, являющихся частью реализации класса, пообщему правилу: имена, начинающиеся с _, не должны присутствовать в частях программы, открытыхдля общего использования.

Имен, начинающихся с двойного символа подчеркивания, лучше вообщеизбегать (даже для членов).Вот менее практичный, но более подробный пример:class X {// по умолчанию частная часть классаint priv;protected:int prot;public:int publ;void m();};Для члена X::m доступ к членам класса неограничен:void X::m(){priv = 1;prot = 2;publ = 3;}// нормально// нормально// нормальноЧлен производного класса имеет доступ только к общим и защищенным членам:class Y : public X {void mderived();};Y::mderived(){priv = 1;prot = 2;publ = 3;////////ошибка: priv частный членнормально: prot защищенный член, аmderived() член производного класса Yнормально: publ общий член}В глобальной функции доступны только общие члены:void f(Y* p){p->priv = 1;p->prot = 2;p->publ = 3;////////}172ошибка: priv частный членошибка: prot защищенный член, а f()не друг или член классов X и Yнормально: publ общий членБьерн Страуструп.Язык программирования С++6.6.2 Доступ к базовым классамПодобно члену базовый класс можно описать как частный, защищенный или общий:class X {public:int a;// ...};class Y1 : public X { };class Y2 : protected X { };class Y3 : private X { };Поскольку X - общий базовый класс для Y1, в любой функции, если есть необходимость, можно(неявно) преобразовать Y1* в X*, и притом в ней будут доступны общие члены класса X:void f(Y1* py1, Y2* py2, Y3* py3){X* px = py1;// нормально: X - общий базовый класс Y1py1->a = 7;// нормальноpx = py2;// ошибка: X - защищенный базовый класс Y2py2->a = 7;// ошибкаpx = py3;// ошибка: X - частный базовый класс Y3py3->a = 7;// ошибка}Теперь пусть описаныclass Y2 : protected X { };class Z2 : public Y2 { void f(); };Поскольку X - защищенный базовый класс Y2, только друзья и члены Y2, а также друзья и члены любыхпроизводных от Y2 классов (в частности Z2) могут при необходимости преобразовывать (неявно) Y2* вX*.

Кроме того они могут обращаться к общим и защищенным членам класса X:void Z2::f(Y1* py1, Y2* py2, Y3* py3){X* px = py1;// нормально: X - общий базовый класс Y1py1->a = 7;// нормальноpx = py2;// нормально: X - защищенный базовый класс Y2,// а Z2 - производный класс Y2py2->a = 7;// нормальноpx = py3;// ошибка: X - частный базовый класс Y3py3->a = 7;// ошибка}Наконец, рассмотрим:class Y3 : private X { void f(); };Поскольку X - частный базовый класс Y3, только друзья и члены Y3 могут при необходимостипреобразовывать (неявно) Y3* в X*. Кроме того они могут обращаться к общим и защищенным членамкласса X:void Y3::f(Y1* py1, Y2* py2, Y3* py3){X* px = py1;// нормально: X - общий базовый класс Y1py1->a = 7;// нормальноpx = py2;// ошибка: X - защищенный базовый класс Y2py2->a = 7;// ошибкаpx = py3;// нормально: X - частный базовый класс Y3,// а Y3::f член Y3py3->a = 7;// нормально173Бьерн Страуструп.Язык программирования С++}6.7 Свободная памятьЕсли определить функции operator new() и operator delete(), управление памятью для класса можновзять в свои руки.

Это также можно, (а часто и более полезно), сделать для класса, служащего базовымдля многих производных классов. Допустим, нам потребовались свои функции размещения иосвобождения памяти для класса employee ($$6.2.5) и всех его производных классов:class employee {// ...public:void* operator new(size_t);void operator delete(void*, size_t);};void* employee::operator new(size_t s){// отвести память в `s' байтов// и возвратить указатель на нее}void{//////}employee::operator delete(void* p, size_t s)`p' должно указывать на память в `s' байтов,отведенную функцией employee::operator new();освободить эту память для повторного использованияНазначение до сей поры загадочного параметра типа size_t становится очевидным.

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

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

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