Главная » Просмотр файлов » лекции (1998) (Буров)

лекции (1998) (Буров) (1161123), страница 23

Файл №1161123 лекции (1998) (Буров) (лекции (1998) (Буров)) 23 страницалекции (1998) (Буров) (1161123) страница 232019-09-19СтудИзба
Просмтор этого файла доступен только зарегистрированным пользователям. Но у нас супер быстрая регистрация: достаточно только электронной почты!

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

void Sort (T *a, int l, int r);

l, r – границы массива.

В сортировке будут использоваться операции сравнения. Компилятор сгенерирует корректный текст функции сортировки в том случае, если он будет иметь какое-то из двух объявлений, написанных выше, будет иметь определение функции Sort и соответствующий контекст конкретизации. Если к объектам типа T не будет применима операция «меньше», то компилятор на строчке, где конкретизируется функция, выдаст сообщение об ошибке.

Осталось выяснить, каким образом конкретизируется функция. В отличии от классов, где присутствуют некие указания на конкретизацию (вместо “T” – “int”, вместо “size” – “20”), когда генерировать функции – решает компилятор, либо он дает возможность программисту указать место, где следует сгенерировать функции. Но в общем случае современные системы программирования обладают некоторым интеллектом, чтобы избегнуть избыточного дублирования кода. Речь идет о генерации функций членов шаблонного класса.

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

Vector <int> a1(20);

Vector <char> a2(256);

int a3[64];

char s[16]

- Sort(a1);

- Sort(a2);

- Sort(a3,0,63);

- Sort(s,0,15);

Мы не вводим новых имен функций – здесь работает механизм перекрытия. Вначале компилятор пытается отыскать точное отождествление (не шаблонную функцию, у которой в параметре Vector <int>), если не находит, то ищет шаблонную функцию с точным отождествлением. Это отождествление он находит. Каким образом? Он смотрит, у нас есть функция-шаблон Sort с одним параметром:

void Sort (Vector <T> & x);

у нее есть ссылка на вектор T. Что выступает в качестве класса T? В качестве класса T выступает int. Действительно происходит некое отождествление с образцов, а именно, вектор “T&” отождествляется с вектором “int”. Следовательно, можно брать первый шаблон для функции Sort для int и генерировать код.

Аналогично для Sort(a2).

В случае трех параметров компилятор находит прототип с тремя параметрами и использует их.

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

Интересно то, что в первой версии шаблонов запрещались параметры-переменные в шаблонных функциях. Говорилось, что параметрами шаблонных функций могут быть только классы. То есть типовые параметры. Требовалось (и требуется), чтобы формальный парамет «тип» находился где-то в списке формальных параметров шаблонных функций. Ошибочным будет следующее определение шаблона:

template <class T> T& f( );

Почему? Механизм конкретизации шаблонов основан на правилах перекрытия. В начале наиболее точные (тождественные) совпадения. Кстати, может быть описана и не шаблонная функция Sort, главное, чтобы не было соответствия по параметрам. Следует вспомнить, что в C++ правила перекрытия определяются только по контексту параметров, но не по типу возвращаемых значений (чтобы не анализировать всевозможные контексты, в которых можно обращаться к функции).

Если мы пишем:

f( );

как мы можем провести здесь отождествление? Никак. Это означает, что T должен появляться в списке параметров. Ведь компилятор смотрит на прототип шаблона, затем на список параметров, и пытается произвести отождествление. В принципе, все просто, но вот списочек возможных контекстов, по которым производится отождествление – длинноват (порядка 15 пунктов).

Сложный вопрос – почему были проблемы с параметрами-переменными. Потому что произвести отождествление с именем просто, а что делать с размером?

Сейчас это ограничение снято, потому что в некоторых случаях можно написать:

int a[20]

f(a);

здесь компилятор может понять размер массива. Если у нас:

int *b;

или

extern c [];

когда размер переменной не известен, компилятор выдаст ошибку. Поэтому в первых версиях параметр-переменная запрещалась, как вид.

Ну и есть контексты, для которых все корректно:

template <class T, int S>

T & f (Stack <T,S> &S);

теперь

Stack <int, 64> S; - корректно

Мы помним, что определение:

template <class T> T& f( ); - ошибочно

Но если очень хочется, то мы можем определить некоторый класс, который будет содержать лишь одну функцию f ( ). Вместо ошибочного объявления мы можем написать несколько сложных:

template <class T> class F {

public:

static T & f( );

}

здесь уже никаких проблем нет, и мы можем писать:

F<int>::f( );

Мы явным образом указываем контекст. С помощью такого трюка мы обходим ограничение.

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

Возникает вопрос, почему, если концепция статической параметризации настолько хороша, другие языки (Delphi, Java) не поддерживают статическую параметризацию? А можно ли что-то заменить? Можно ли шаблоны смоделировать через другие средства языка. Когда мы говорили о контейнерах, то их следует рассматривать, как шаблонные классы, более того, в любой реализации C++ будет некая библиотека контейнеров, которая позволяет генерировать произвольные контейнеры. В чем достоинства и недостатки?

Достоинства очевидны, если у нас есть хэш-таблица, то достаточно реализовать код работы с ней (достаточно нетривиальный код) только один раз, а затем лишь пользоваться.

Недостатки в том, что она все же статическая. Мы не можем написать гетерогенные контейнеры, которые будут содержать объекты разных классов. Путь через (void *) делает большую дыру в защите. Да и само использование (void *) делает контейнеры ненужными.

Механизм шаблонов – очень сильное оружие, которое может рвануть в руках. Например, если мы пишем вектора для 50 типов данных, то у нас будут сгенерированы 50 одинаковых функций, и компилятор не обладает интеллектом, чтобы увидеть эту общность. Заметим, что контейнеры типа вектора на Ada можно написать, не теряя общности так, что будет сгенерирована только одна порция кода – эффективность значительно больше. Когда же программист начинает писать шаблоны сам, особенно не задумываясь над тем, что же нужно делать и что происходит, то обнаруживает в конце невероятное разбухание кода. Например:

template <class T> class Vector {

T** body; };

T1* Vector <T1*> V1;

T2* Vector <T2*> V2;

T5* Vector <T5*> V5;

Мы получим 5 различных функций.

Глава 7. Исключительные ситуации в языках программирования.

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

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

ON ситуация оператор

Примерно то же самое есть сейчас в языке Visual Basic. При возникновении ситуации (набор которых обычно был в базисе языка), выполнялся некий оператор (обычно это вызов подпрограммы), после которого, программа возобновлялась после точки его вызова, либо останавливалась. Ситуация определяет некоторое условие, при выполнении которого (далее в программе) сразу выполнялся оператор. К ситуациям, например, относились следующие константы: OVERFLOW, ERROR, ENDFILE. Что является ситуацией? С одной стороны – это набор некоторых ошибочных условий, т.е. аварийная ситуация, с другой стороны – это условия, которые зависят от внешней среды, такие как ENDFILE. С этой точки зрения, ON-ситуации можно рассматривать, как реакции на события, которые в принципе запланированы, но которые хотелось бы обрабатывать несколько нестандартным образом. Это очень похоже на те механизмы выхода из середины цикла, которые мы изучали, когда говорили о структурах управления. Сейчас существует устоявшаяся точка зрения, что исключения – это действительно аварийные ситуации, которые требуют нестандартного подхода, хотя их можно использовать и для какого-то нестандартного способа передачи управления, но этот подход является несколько порочным.

Механизм исключительных ситуаций практически одинаков во всех языках программирования, которые мы сейчас рассматриваем, что свидетельствует о том, что программисты пришли к некоторому консенсусу. Исключения, в отличие от шаблонов, есть в большом количестве языков, более того, языки, в которых они не поддерживаются, не являются языками индустриального программирования. В частности, отсутствие этой концепции в системе визуального программирования Power Builder значительно сводит на нет все достоинства этой системы.

В ранних языках программирования, исключения очень напоминали механизм обработки прерываний, реализованный на несколько более высоком уровне. Но такой механизм устарел. Современный подход, мы видим, прежде всего, в языке Ада, который с этой точки зрения повлиял и на С++. И практически в неизменном виде этот механизм присутствует в таких системах, как Delphi и Java. Самый простой механизм обработки исключений в Аде, потому что там нет наследования. Основное отличие языков Delphi и Java от C++ и Ады, состоит в том, что в первом случае, исключения являются имманентной частью языка. Мы будем рассматривать исключения во всех языках сразу, но по аспектам.

1. Объявление исключений.

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

В языках Delphi и Java исключения представляют собой классы. В С++ исключения – это произвольный тип данных, т.е. исключения могут быть сопоставлены типу int или char*, и т.д. С++ ввел совершенно новый подход, потому что просто идентификатор исключения несет в себе слишком мало информации. Если, например, произошел выход за границу массива, то хотелось бы знать, за границу какого массива, в какой точке, и т.д. В С++ мы можем в момент возникновения ошибки передать нужную информацию через объект исключения, туда, где она может пригодится. Java и Delphi отчасти разделили подход С++, но ограничились только классами, которые являются наследниками базовых классов (Throwable и Exception соответственно).

В классе Exception языка Delphi, например, уже есть конструктор Create, параметром которого является строка, в которую можно записать сообщение об ошибке. Если нам нужна более содержательная информация об ошибке, то мы можем вывести из этого класса свой класс, добавив в него новые возможности. Java разделяет все исключения на два класса – пользовательские, которые возбуждает пользователь, и системные, которые возбуждаются аппаратно, либо виртуальной машиной. На системные исключения программист может не реагировать, а на пользовательские исключения – обязан реагировать. Наличие базисного класса исключений дает очень много, и из-за отсутствия такого класса в С++ программу приходится начинать с конструирования своего механизма исключений.

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

2. Определение исключения.

Для того, чтобы определить исключение, мы должны задать некий код, который обрабатывает исключения. Зачем исключения понадобилось вводить как особую языковую конструкцию? Прежде всего, для того, чтобы отделить нормальный код (код, в котором возникают ошибки) от кода по устранению ошибок.

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

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

В языке Ада предполагается, что ошибка может возникнуть в любом месте программы и в любом месте программы ее можно обработать. Единицей кода, в которой может произойти исключение, является блок операторов, ограниченный begin и end. Блоком является тело подпрограммы, блоком является инициализационная часть тела пакета, и т.д. Везде, где могут стоять операторы, в конце некоторой их последовательности может вставляться блок по обработке исключений:

exception

when список_имен_исключений =>

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

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

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

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