Лекции (1129116), страница 20

Файл №1129116 Лекции (Лекции) 20 страницаЛекции (1129116) страница 202019-05-11СтудИзба
Просмтор этого файла доступен только зарегистрированным пользователям. Но у нас супер быстрая регистрация: достаточно только электронной почты!

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

Понятно, что инкапсуляция происходит за счет технологической дисциплины. Например, использование extern в программе – плохой стиль. Так как это означает, что программист сам описывает контекст и может ошибиться.

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

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

Вобщем, можно понять, что независимая трансляция – не очень хорошая вещь.

Раздельная зависимая трансляция

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

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

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

Modula-2

С этой точки зрения в Modula-2 самая простая ситуация: у нас есть ТБ, которая состоит из всех модулей определений. Транслятор использует только модули определений. Поэтому никаких проблем со скрытыми типами нет, но только в случае, если АТД пресдставлен указателем. Прежде всего, это из-за простоты. С другой стороны можно обеспечить все контроли межмодульных интерфейсов. В единице компиляции у нас может быть import (это и есть указание контекста), либо:

IMPORT M;

либо

FROM M IMPORT …;

Oberon

В Oberon все еще проще. В нем все – один модуль, вся программная библиотека – библиотека модулей:

MODULE M;

END;

Возникает вопрос – что хранится в трансляционной библиотеке? В ней хранятся все имена (для каждого модуля заведен соответствующий раздел), помеченные знаком “*” или “*-“ (последние – это переменные только для чтения).

Больше нагрузки ложится на транслятор. Например, в Modula-2, так как были разделены уже заранее, на уровне исходных текстов, модули определений и соответствующие модули реализаций, то это позволяло при трансляции нужна была только трансляционная библиотека, и мы не должны были транслировать все сразу. То есть минимизируется количество перекомпиляций, что во время создания языка было достаточно критическим параметром.

Для достижения аналогичных результатов в языках с независимой компиляцией (например, С) вводится ряд внешних утилит. Так в Unix язык C сразу «оброс» такими программами, как make, lint. Первая занимается как раз определением зависимостей между исходными текстами, файлами заголовков, объектными модулями и, собственно, запускаемым файлом, данные зависимости определяются по временным отметкам файлам. Вторая (lint) – это верификатор межмодульных связей, которому на вход дается весь проект, и поскольку ему (в отличие от стандартного компилятора) теперь доступны все файлы, он проверяет ошибки межмодульных связей, то есть он делает то, что должен был бы делать компилятор С, если бы делал раздельную зависимую трансляцию. Понятно, что все эти утилиты вместе образуют некоторую среду, позволяющую как-то избавляться от проблем.

На сегодняшний день среды разработки на C++ включает транслятор, утилиту make и верификатор связей, подобный lint. Например, и BC++ и MSVC всегда генерируют makefile.

Возвращаясь к языку Oberon следует сказать, что на первый взгляд все преимущества, связанные с минимизацией времени трансляции кажутся потерянными, поскольку у нас в явном виде трансляционная библиотека не определяется, а определяется она самим транслятором. Что будет, если изменить какой-то модуль? Будут перетранслированы все клиентские модули. Получается, что преимущества разделения на модули определений и реализации, которые имеются хотя бы в Modula-2 потеряны. На самом же деле это не есть недостаток языка. Это недостаток транслятора.

Опять вернемся к языку С. Заметим, что если в header файле добавить пробел или удалить комментарий, то будут перетранслированы все клиентские модули, хотя с разумной точки зрения это бессмысленно. А вот в Turbo Pascal, где реализована фактически обероновская схема (модуль реализации и определения объединены в одном), подобного не произойдет. Будет на всякий случай перекомпилирован сам модуль, но клиентские части останутся прежнеими Почему? Дело в том, что оттранслированный unit в Turbo Pascal в начале состоит из и определений, а затем из части реализации. Поэтому транслятор при перекомпиляции смотрит – насколько изменилось определение – при добавлении, например, пробела сгенерированный двоичный код никак не изменяется. Также делает Oberon.

Таким образом, соединение воедино частей реализации и определений в одном модуле неприятных последствий не оказывает.

В С/С++ есть механизм предкомпилированных header’ов, который почти повторяет эту схему, но сам механизм гораздо более сложный, чем чистая реализация в Turbo Pascal или Oberon.

Ada

В Ada, когда мы говорили об определении новых типов, то видели модули двух видов: спецификация пакета и тело пакета:

package P is

end P;

package body P is

end P;

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

Мы говорили, что недостатком линейной схемы организации модулей, когда все модули равноправны, явлется неподдержка сформировавшейся методологии программирования, такая линейка модулей поддерживает программирование «снизу вверх», а есть еще и «сверху вниз». В этом плане зависимости между модулями в Modula-2 – односторонии. Модуль М не знает, куда его экспортируют, с другой стороны есть клиентские модули, которые явно говорят, что они импортируют:

IMPORT M;

В Ada есть примеры более сложной связи, а именно, двухсторонней связи. Это связано с тем, что раздельная трансляция поддерживается в Ada на всех уровнях. Мы уже говорили, что в Ada могут быть вложенные пакеты. Внутри одного пакета может быть описан другой:

package P is

package P1 is

end P1;

end P;

package body P is

package body P1 is

end P1;

end P;

Такая схема поддерживает программирования поддерживает схему «сверху вниз»: пакет P1 имеет смысл только в контексте модуля P (в схеме «снизу вверх» P1 имеет смысл сам по себе). Получается, если мы не разрешим раздельную трансляцию P1, то тело P может сильно разбухнуть. Возникает вопрос – как это сделать, ведь P1 локально внутри P? В Ada были введены специальные конструкции. Естественно, что интерес представляет раздельная компиляция тела вложенного пакета. Мы пишем следующим образом:

package P is

package P1 is

end P1;

end P;

А тело пакета оформляется следующим образом, в нем появляется заглушка для тела P1:

package body P is

package body P1 is separate;

end P;

Ключевое слово separate говорит, что тело P1 будет транслироваться отдельно. Где же будет находится это тело?

separate (P);

package body P1 is

end P1;

В начале мы указываем, что P1 вложен в P (ведь у нас может быть несколько пакетов с именем P1 на различных уровнях)

В результате мы имеем пример двусторонней, более сложной связи. Причем, можно таким образом поступать и с телами процедур.

Пока мы еще ничего не сказали о том, как в Ada указывается контекст трансляции (КТ). Это очень просто – раздельно транслируемый модуль отличается от обычного, находящегося в файле лишь наличием в начале определения WITH <список имен>. Кроме того, может быть добавлена конструкция USE <список имен>.

WITH делает объекты непосредственно видимыми в данном модуле. Если есть:

package P is

TYPE T IS ..

X: T;

end P;

и другая единица компиляции:

with P; use P;

package Q is

Y: P.T;

end Q;

package body Q is

Y:=P.X;

end Q;

В результате P видимо непосредственно, а все объекты внутри P – потенциально.

Для чего нужна конструкция USE? Используя ее мы можем писать, а можем не писать уточнение “P.”, то есть она работает, как и вообще USE в теле пакета.

Можно разделить процедуры:

package body P1 is

procedure P2 is separate;

end P1;

и в другом физическом модуле:

separate (P1) procedure P2 is

end P2;

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

Заметьте, что в Modula-2 и Oberon совсем не так – если пишется библиотечный модуль, то мы обязаны транслировать его отдельно. Зачем сделано по-другому в Ada? Для гибкости и удобства программиста.

Но за все надо платить. В Ada приходится платить приватной частью спецификаций, а именно, то, что сделано в Oberon и Modula-2 (если изменяется реализация, то клиентские модули не перетранслируются), в Ada не сделано. Поскольку спецификация пакета выглядит следующим образом:

package P is

type T is private;

private

type T is record … end record;

end P;

Понятно, что это есть реализация, здесь нет никаких текстов процедур, поскольку инкапсулированный код находится в теле пакета P. И изменение тел процедур (приватных) для типа T – оно инкапсулировано. Если тело P транслируется отдельно, то никакого изменения в клиентских модулях не требуется, их перетранслировать не нужно.

Если же мы меняем структуру типа T, то следует перетранслировать все клиентские части. Это – недосаток. Конечно, с современной точки зрения это несущественно.

C++

Заметьте, что на первый взгляд классовые языки, такие как C++ обладают такими же недостатками. Если есть:

class X{

public: // если абстрактный тип данных, то эта часть состоит

//только из функций

private: // эта часть состоит из структур данных

// и приватных функций

};

Следует подчеркнуть, что публичная часть должна состоять только из функций в АТД, но не обязательно в абстрактном классе.

Получается, что любое изменение приватной части приводит к перекомпиляции всех клиентских модулей, несмотря на то, что интерфейс не изменился. На первый взгляд, это кажется не очень большим недостатком, однако, учитывая независимую трансляцию модулей в C++ это иногда приводит к большим накладным расходам, ибо большинство компилируемых единиц приходится не на написанный код, а на используемые библиотеки (win32Api, Motif и т.д.). Иногда ¾ и более компилируемого текста приходится на эти библиотеки. Опять же современные средства программирования на C++ содержат концепцию прекомпилированных header’ов, то есть эти заголовки хранятся в специальном формате, и компилятор перед обработкой текста пытается что-то взять сначала оттуда. Однако, программисты, как на MSVC, так и на BC++ знают, что это уменьшает время трансляции и добавляет немного головной боли, ибо сам язык такой концепции не поддерживает.

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

Java

В Java безусловно трансляция раздельная и зависимая. Еще хорошо то, что когда мы указываем контекст, мы всегда указываем имя некоторого логического модуля, который одновременно является и единицей компиляции и должен содержаться в каком-то файле. Логический модуль в Java – это класс. Есть файл (единица компиляции). Есть физический модуль (пакет), он состоит из ряда файлов. Больше в Java ничего нет – там нет ни глобальных переменных, ни глобальных функций.

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

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

Список файлов лекций

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