Главная » Просмотр файлов » М. Бен-Ари - Языки программирования. Практический сравнительный анализ (2000)

М. Бен-Ари - Языки программирования. Практический сравнительный анализ (2000) (1160781), страница 44

Файл №1160781 М. Бен-Ари - Языки программирования. Практический сравнительный анализ (2000) (М. Бен-Ари - Языки программирования. Практический сравнительный анализ (2000)) 44 страницаМ. Бен-Ари - Языки программирования. Практический сравнительный анализ (2000) (1160781) страница 442019-09-19СтудИзба
Просмтор этого файла доступен только зарегистрированным пользователям. Но у нас супер быстрая регистрация: достаточно только электронной почты!

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

private:

void echo(char с);

friend class Keyboard; // Разрешить классу Keyboard вызывать echo

};

class Keyboard {

private:

void put_key(char c);

friend class Display; // Разрешить классу Display вызывать put_key

};

Использование механизма friend позволяет избежать как создания неоправ­данно большого числа открытых (public) подпрограмм, так и объединения двух классов в один большой класс только потому, что они имеют одну-един-ственную общую операцию.

С помощью friend можно также решить проблему синтаксиса, связанную с тем фактом, что подпрограмма в классе C++ имеет отличимый получатель, такой как obj1 при вызове obj1.proc(obj2). Это привносит в подпрограммы асимметрию, в противном случае они были бы симметричны по параметрам. Стандартный пример — перегрузка арифметических операций. Предполо­жим, что мы хотим перегрузить «+» для комплексных чисел и в то же время позволить операции неявно преобразовать параметр с плавающей точкой в комплексное значение:

complex operator + (float);

complex operator + (complex);

Рассмотрим выражение х + у, где одна из переменных (х или у) может быть с плавающей точкой, а другая комплексной. Первое объявление правильно для комплексного х и плавающего у, потому что х+у эквивалентно x.operator+(y), и, стало быть, будет диспетчеризованно отличимому получателю комплекс­ного типа. Однако второе объявление для х+у, где х имеет тип с плавающей точкой, приведет к попытке диспетчеризоваться к операции с плавающей точкой, но операция была объявлена в комплексном классе.

Решение состоит в том, чтобы объявить эти операции как «друзей» класса, а не как операции класса:

friend complex operator + (complex, complex);

friend complex operator + (complex, float);

friend complex operator + (float, complex);

Хотя эта конструкция популярна в языке C++, на самом деле существует луч­шее решение, при котором не требуется friend.

Оператор «+=» можно определить как функцию-член (см. справочное руководство, стр. 249), а затем «+» можно определить как обычную функцию за пределами класса:

complex operator + (float left, complex right)

{

complex result = complex(left);

result + = right; // Результат является отличимым получателем

return result;

}

Спецификаторы доступа в языке C++

Когда один класс порождается из другого, мы вправе спросить, имеет ли производный класс доступ к компонентам базового класса. В следующем примере database (база данных) объявлена как приватная, поэтому она недо­ступна в производном классе:

class Airplanes {

private:

Airplane_Data database [100];

};

class Jets : public Airplanes {

void process Jet(int);

};

void Jets::process_jet(int i)

{

Airplane_Data d = database[i] ; // Ошибка, нет доступа!

};

Если объявлен экземпляр класса Jets, он будет содержать память для database, но этот компонент недоступен для любой подпрограммы в произ­водном классе.

Есть три спецификатора доступа в языке C++:

• Общий (public) компонент доступен для любого пользователя класса.

• Защищенный (protected) компонент доступен внутри данного класса и внутри производного класса.

• Приватный компонент доступен только внутри класса.

В примере, если database просто защищенный, а не приватный член класса, к нему можно обращаться из производного класса Jets:

class Airplanes {

protected:

Airplane_Data database[100];

};

class Jets : public Airplanes {

void process_jet(int);

};

void Jets::process_jet(int i)

{

Airplane_Data d = database[i]; // Правильно, в производном классе

};

Однако это не очень хорошая идея, потому что она ставит под удар абстрак­цию. Вероятно, было бы лучше даже для производного класса манипулиро­вать унаследованными компонентами, используя общие или защищенные подпрограммы. Тогда, если внутреннее представление изменяется, нужно из­менить только несколько подпрограмм.

Язык C++ допускает изменение доступности компонентов класса при объявлении производного класса. Обычно порождение бывает общим (public). Так было во всех наших примерах, и при этом сохранялась доступность, заданная в базовом класс. Однако вы также можете задать приватное порожде­ние, тогда и общие, и защищенные компоненты становятся приватными:

class Airplanes {

protected:

Airplane_Data database [100];

};

class Jets : private Airplanes { // Приватное порождение

void process_jet(int);

};

void Jets::process_jet(int i)

{

Airplane_Data d = database[i]; // Ошибка, нет доступа

};

Пакеты-дети в языке Ada

В языке Ada только тело пакета имеет доступ к приватным объявлениям. Это делает невозможным непосредственное совместное использование пакетами приватных объявлений так, как это можно делать в языке C++ с защищенны­ми объявлениями. В языке Ada 95 для совместного использования приватных объявлений доставлено специальное средство структурирования, так называ­емые пакеты-дети (child packages). Здесь мы ограничим обсуждение пакетов-детей только для этой цели, хотя они чрезвычайно полезны в любой ситуации, когда вы хотите расширить существующий пакет без его изменения или пере­компиляции.

Зададим приватный тип Airplane_Data, определенный в пакете:

package Airptane_Package is

type Airplane_Data is tagged private;

private

type Airplane_Data is tagged

record

ID:String(1..80);

Speed: Integer range 0.. 1000;

Altitude: Integer 0.. 100;

end record;

end Airplane_Package;

Этот тип может быть расширен в пакете-ребенке:

package Airplane_Package.SST_Package is

type SST_Data is tagged private;

procedure Set_Speed(A: in out SST_Data; I: in Integer);

private

type SST.Data is new Airplane_Data with

record

Mach: Float;

end record;

end Airplane_Package.SST_Package;

Если задан пакет P1 и его ребенок Р1 .Р2, то Р2 принадлежит области родителя Р1, как если бы он был объявлен сразу после спецификации родителя. Внут­ри закрытой части и теле ребенка видимы приватные объявления родителя:

package body Airplane_Package.SST_Package is

procedure Set_Speed(A: in out SST_Data; I: in Integer) is

begin

A.Speed := I; -- Правильно, приватное поле в родителе

end Set_Speed;

end Airplane_Package.SST_Package;

Конечно, общая часть ребенка не может обращаться к закрытой части родите­ля, иначе ребенок мог бы раскрыть секреты родительского пакета.

15.3. Данные класса

Конструкторы и деструкторы

Конструктор (constructor) — это подпрограмма, которая вызывается, когда создается объект класса; когда объект уничтожается, вызывается деструктор (destructor). Фактически, каждый объект (переменная), определенный в ка­ком-либо языке, требует выполнения некоторой обработки при создании и уничтожении переменной хотя бы для выделения и освобождения памяти. В объектно-ориентированных языках программист может задать такую обра­ботку.

Конструкторы и деструкторы в языке C++ могут быть определены для лю­бого класса; фактически, если вы не определяете их сами, компилятор обес­печит предусмотренные по умолчанию. Синтаксически конструктор — это подпрограмма с именем класса, а деструктор — то же имя с префиксным сим­волом «~»:

class Airplanes {

private:

C++

Airplane_Data database [100];

int current_airplanes;

public:

Airplanes(int i = 0): current_airplanes(i) {};

~Airplanes();

};

После создания базы данных Airplanes число самолетов получает значение па­раметра i, который по умолчанию имеет значение ноль:

Airplanes а1 (15); // current_airplanes =15

Airplanes a2; //current_airplanes = О

Когда база данных удаляется, будет выполнен код деструктора (не показанный). Можно определить несколько конструкторов, которые перегружаются на сигнатурах параметров:

class Airplanes {

public:

Airplanes(int i = 0): current_airplanes(i) {};

C++

Airplanes(int i, int j): current_alrplanes(i+j) {};

~Airptartes();

};

Airplanes a3(5,6); // current_airplanes = 11

В языке C++ также есть конструктор копирования (copy constructor), который дает возможность программисту задать свою обработку для случая, когда объ­ект инициализируется значением существующего объекта или, в более общем случае, когда один объект присваивается другому. Полное определение кон­структоров и деструкторов в языке C++ довольно сложное; более подробно см. гл. 12 справочного руководства по языку C++.

В языке Ada 95 явные конструкторы и деструкторы обычно не объявля­ются. Для простой инициализации переменных достаточно использовать зна­чения по умолчанию для полей записи:

type Airplanes is tagged

record

Current_Airplanes: Integer := 0;

end record;

Ada


или дискриминанты (см. раздел 10.4):

type Airplanes(lnitial: Integer) is tagged

record

Current_Airplanes: Integer := Initial;

end record;

Программист может определить свои обработчики, порождая тип из абстрак­тного типа, называемого управляемым (Controlled). Этот тип обеспечивает аб­страктные подпрограммы для Инициализации (Initialization), Завершения (Finalization) и Корректировки (Adjust) для присваивания, которые вы можете заместить нужными вам программами. За деталями нужно обратиться к пакету Ada. Finalization, описанному в разделе 7.6 справочного руководства по языку Ada.

Class-wide-объекты

Память распределяется для каждого экземпляра класса:

C++

class С {

chars[100];

};

С с1,с2; //по 100 символов для с1 и с2

Иногда полезно иметь переменную, которая является общей для всех экземп­ляров класса. Например, чтобы присвоить порядковый номер каждому экзем­пляру, можно было бы завести переменную last для записи последнего при­своенного номера. В языке Ada это явно делается с помощью включения обычного объявления переменной в теле пакета:

package body P is

Last: Integer := 0;

Ada

end P;

в то время как в языке'C++ нужно воспользоваться другим синтаксисом:

class С {

C++

static int last; //Объявление

chars[100];

};

int C::last = 0; // Определение, доступное за пределами файла

Спецификатор static в данном случае означает, что будет заведен один CW-объект*. Вы должны явно определить компонент static за пределами определе­ния класса. Обратите внимание, что статический (static) компонент класса имеет внешнее связывание и может быть доступен из других файлов, в отли­чие от статического объявления в области файла.

Преобразование вверх и вниз

В разделе 14.4 мы описали, как в языке C++ значение порожденного класса может быть неявно преобразовано в значение базового класса. Это называет­ся преобразованием вверх (up-conversion), потому что преобразование делается вверх от потомка к любому из его предков. Это также называется сужением (narrowing), Потому что производный тип «широкий» (так как он имеет допол­нительные поля), в то время как базовый тип «узкий», он имеет только поля, которые являются общими для всех типов в производном семействе. Запом­ните, что преобразование вверх происходит только, когда значение произ­водного типа непосредственно присваивается переменной базового типа, а не когда указатель присваивается от одной переменной другой.

Преобразование вниз (down-conversion) от значения базового типа к значе­нию производного типа не допускается, поскольку мы не знаем, какие значе­ния включить в дополнительные поля. Рассмотрим, однако, указатель на ба­зовый тип:

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

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

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

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