лекции (2007), страница 8

2019-09-19СтудИзба

Описание файла

Документ из архива "лекции (2007)", который расположен в категории "". Всё это находится в предмете "языки программирования" из 7 семестр, которые можно найти в файловом архиве МГУ им. Ломоносова. Не смотря на прямую связь этого архива с МГУ им. Ломоносова, его также можно найти и в других разделах. .

Онлайн просмотр документа "лекции (2007)"

Текст 8 страницы из документа "лекции (2007)"

END stacks;

IMPORT Stacks;

VAR S: Stacks.Stack;

Stacks.Push(S,I);

I:=Stacks.Pop(S);

MODULE Stacks;

const S_SIZE=128;

TYPE Stack * = RECORD

B: …

TOP: INTEGER;

END;

PROCEDURE PUSH*(…)

PROCEDURE POP*(…)

VAR Done *-: Boolean;…


Оберон2

END stacks;

Язык Ada - понятие пакета (некий аналог модуля в языке Modula-2).

Спецификация пакета:

package имя is

объявления

end имя

Тело пакета:

package body имя is

реализация

end имя

Имена пакетов должны быть уникальными. Пакет, в котором определён ТД, называется определяющим пакетом. Главное отличие от других ЯП (Modula-2, Oberon, Delphi) - нет простой, линейной структуры модулей; модули могут вкладываться друг в друга. Есть "главный" пакет STANDART, в который вкладываются все остальные модули.

Видимость: имена самих пакетов видимы непосредственно, имена из пакетов видимы потенциально (по имя_пакета.имя)

Пример пакета:

package Complex_numbers is

type Complex is record

Re, Im : Float;

end record;

function "+" (X,Y : in Complex) return Complex;

...

end Complex_numbers;

Как видно, можно перекрывать операции, причём как пользовательские, так и стандартные.

Но возникает проблема, связанная с видимостью:

X, Y, Z: Complex_numbers.complex;

Поскольку имя "+" из пакета Complex_numbers видимо только потенциально, нельзя просто написать

X := Y + Z;

Придётся писать так:

X := Complex_numbers."+"(Y, Z);

Получается, что весь смысл перекрытия стандартных операций теряется: нет никакой разницы между перекрытием "+" или объявлением новой функции Plus, если в обоих случаях к ним придётся обращаться одинаково, через Complex_numbers.

Поэтому в языке Ada реализован механизм, который реализует непосредственную видимость к нужным именам. Это конструкция "use":

use список_имён_пакетов;

Тогда все имена из пакетов, указанных в этом списке, станут видимы непосредственно. В нашем примере:

use Complex_numbers;

X, Y, Z : Complex;

X := Y + Z;

Но при использовании конструкции "use" может возникнуть другая проблема - конфликт имён. Правда, если конфликт возникает в именах операций (например, в двух разных пакетах определены функции или процедуры с одинаковыми именами), то, если профили функций разные, компилятор может различить их по типу операндов.

Таким образом, пока производится use только тех модулей, в которых одноимённые функции имеют разные профили, конфликта не возникает. А вот как только будет подключен модуль, в котором у одноимённой функции профиль повторяется или описан тип с таким же именем, это имя вообще перестанет быть видимым во избежание конфликта.

Ситуация ещё больше усложняется, когда пакеты вложены друг в друга, и конфликтуют имена, описанные на разных уровнях.

Из-за этого во многих компаниях, занимавшихся промышленным программированием на Ada, для повышения надёжности проектов даже вводились особые правила, запрещающие использование "use".

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

Как уже было сказано, в Ada допускается вложенность пакетов. Вот как это выглядит:

package P is

...

package PP is

...

end PP;

...

end P;

package body P is

...

package body PP is

...

end PP;

...

end P;

Существует два противоположных метода проектирования программ: "сверху-вниз" ("top-bottom") и "снизу-вверх" ("bottom-up"):

"Сверху-вниз": сначала проектируются модули верхнего уровня, потом они "разбиваются" на более мелкие модули, и так далее; вместо модулей нижнего уровня пишутся "заглушки".

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

"Снизу-вверх"- всё наоборот: сначала проектируются модули нижнего уровня, потом на их основе создаются модули более высокого уровня, и так далее, заканчивая верхним уровнем.

Здесь, напротив, модули низкого уровня отлаживать значительно проще, но пока система не завершена полностью, ничего нельзя сказать о её работоспособности и тем показывать её заказчику.

Классы

Класс - это ещё одно средство описания ТД. Преимущество перед модулем состоит в том, что класс одновременно является и структурой, и типом данных (в то время как, например, в языке Ada приходится описывать пакет и определять внутри него тип данных).

Члены класса делятся на два типа: члены-данные и члены-функции.

Синтаксис объявления класса очень похож во всех языках (в основном мы будем рассматривать C++, C#, Java и Delphi). Например, на языке Delphi объявление класса выглядит так:

type T = class (base_class)

procedure P;

объявления_других_членов

end;

procedure T.P;

begin

...

end;

То есть в Delphi четко выполняется принцип РОРИ (разделения, определения, реализации и использования): в объявлении класса могут присутствовать только переменные и прототипы.

В C# и Java принцип РОРИ не выполняется: если описывается функция-член, то необходимо сразу же и указать её реализацию (исключение - чисто виртуальные функции). Это неудобно с точки зрения читабельности, но значительно облегчает отладку. А читабельность достигается другими методами: C# и Java "погружены" в специальные среды разработки, которые предоставляют возможность отображения только интерфейсной части классов, скрывая реализацию.

В C++ принцип РОРИ есть, но необязателен. Тем не менее его обычно выполняют: принято объявление класса помещать в заголовочные файлы (.h, header-файлы), а реализацию - в файлы кода (.cpp).

Члены локализованы внутри классов. Синтаксис обращения везде одинаков: если есть класс X и у него есть член y, то доступ к y осуществляется по X.y (так же, как и у записи). Кроме того, есть модификаторы доступа к членам (напрмер, в C++ это public, private и protected), но это отдельная тема.

Члены класса делятся на статические и нестатические. Статические члены необходимы для работы со статическими данными.

В языке Smalltalk присутствует понятие экземпляра класса. Соответственно, члены делились на члены класса, которые размещались в единственном числе (и могут существовать вне зависимости от того, созданы ли экземпляры этого класса или нет), и на члены экземпляра, которые для каждого экземпляра были свои.

В C++ при работе со статическими данными возникает проблема их размещения: из-за раздельной трансляции компилятор не знает, где находится класс - в заголовочном файле или в файле кода. Поэтому, если у класса X есть статическая переменная static int n, то в файле кода будет необходимо явно её инициализировать: int X::n = -1 .

Члены-функции отличаются от членов-данных практически лишь тем, что им неявно передаётся указатель/ссылка на объект класса, и в теле функции определяется дополнительная переменная:

C++ - указатель this

Delphi, Java – ссылка Self

С# - ссылка this

Со статическими членами-функциями всё аналогично, синтаксис следующий:

C++ - X::f()

C#, Java - X.f()

Если в C++ функция main () должна быть глобальной, то в C# и Java необходимо определить её как статическую в одном из классов:

public static int main (string [] args){...};

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

class X

{

private:

X(){...}

...

public:

static X * Make () {... return new X();}

...

}

Ещё одно понятие, которое появилось в C++ - встраиваемые функции (inline). Это функции, тела которых подставляются в местах их вызова. Это ускоряет быстродействие, так как исчезают операторы перехода, ломающие конвейер команд. Inline-функции похожи на макросы, но более удобны в использовании:

1) Их удобнее описывать. Пример - нахождение максимального из двух чисел:

макрос - #define max (a,b) ((a) < (b)) ? (b) : (a);

inline-функция - inline T max (T a, T b) { return a < b ? b : a;}

2) Inline-функции более надёжны, при их вызове производится проверка и преобразование типов. Если же происходит ошибка, то при использовании inline-фукнкций программист получит сообщение о ней в терминах вызова функции, в то время как макрос выдаст ошибку в терминах макроподстановки.

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

Один из наиболее распространённых примеров вложенности классов - библиотека стандартных шаблонов STL. Внутри любого контейнера STL определяется вложенный класс iterator. Это удобно, так как при работе с STL можно легко заменить один контейнер на другой.

В языке Java для обозначения вложенных классов специально введено понятие статического класса (смысл остаётся прежним):

class X

{

...

public static class Y

{

...

}

...

}

Теперь рассмотрим средства описания особых ссылочных типов, являющихся как бы указателями на функции:

В C++:

int * p; void (* f)();

int X::* p; void (X::* f)();

В Delphi:

type PR e = procedure (int) of T;

Наиболее развитый механизм - в C#: введено понятие делегатного типа (delegate). Каждый объект-делегат представляет собой некоторый список операций ("invocation list"). Пустой список представляется как null. Изменять этот список можно при помощи операторов +, +=, - и -=.

Пример:

class X

{

...

public delegate void g_delegate (int);

...

}

class Y

{

...

public void f (int x) {...};

public static void h (int i) {...};

...

}

Y yobj;

g_delegate gg = new g_delegate (Y.h);

gg += new g_delegate (yobj.f);

gg (1);

Вернёмся к рассмотрению механизма классов. Ещё одна его возможность - управление инициализацией, преобразованием и разрушением объектов. Это осуществляется с помощью специальных функций - конструкторов, деструкторов и операторов преобразований (операторы преобразования есть не только в объектно-ориентированных ЯП).

Конструктор вызывается при создании объекта класса, деструктор - при его уничтожении.

Наиболее сложная и развитая система в C++, так как существует три класса памяти (статическая, квазистатическая и динамическая). В C#, Java и Delphi используется только динамическая память.

В C++ конструктор объекта какого-то класса должен иметь то же имя, что и этот класс. У конструктора нет возвращаемого значения. Конструкторы могут иметь разную семантику (мы рассматриваем какой-то класс X):

X () {...}

X (int i) {...}

X (int i, int j) {...}

X (X &) {...}

X (const X &) {...}

X (T) {...}

X (T &) {...}

X (const T &) {...}

...

Конструктор X () - это конструктор по умолчанию, который вызывается, если явно не был указан вызов какого-либо другого конструктора.

Конструкторы наподобие X (int i) и X (int i, int j) используются, когда необходимо создать объект, инициализированный каким-о специальным образом.

Конструкторы X (X &) и X (const X &) - это конструкторы копирования. При присваивании, когда необходимо сделать копию объекта класса, не всегда правильно просто скопировать значения полей, так как в объектах могут быть, например, ссылки на какие-то динамические структуры, и тогда копия объекта не создаст копии этих структур, а будет ссылаться на структуры исходного объекта. Поэтому принято различать два вида копирования: поверхностное копирование (shallow copy), когда все поля просто копируются побитово (то есть копируется только верхний уровень структуры данных), и глубокое копирование (deep copy), когда вся структура данных копируется полностью.

Конструкторы X (T), X (T &) и X (const T &) - это конструкторы преобразования. Для чего они нужны? Вообще, одной из причин введения классов стала необходимость в средствах лёгкого расширения возможностей языка. Например, программисту может потребоваться комплексный тип данных, и тогда он пишет класс Complex с описанием комплексного типа (скажем, вещественной и мнимой частям соответствуют переменные Re и Im типа float). Для создания комплексного числа из двух вещественных достаточно написать простой конструктор преобразования:

Complex (float a, float b) {Re = a; Im = b;}

Для работы с комплексными числами программист может просто определить в классе функции Plus, Minus, Mult и т.д., но это неудобно (поскольку записывать выражения вроде "a + b * c" в виде "Plus(a, Mult(b, c))" неудобно и ненаглядно). Поэтому обычным приёмом является перекрытие операций. Для рассматриваемого примера в классе достаточно написать короткое перекрытие для каждой операции:

Сomplex operator + (Complex a &, Complex b &) {return Complex(a.Re + b.Re, a.Im + b.Im);}

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