Главная » Просмотр файлов » Системы программирования

Системы программирования (1119744), страница 6

Файл №1119744 Системы программирования (Экзамен. Варианты заданий и ответы) 6 страницаСистемы программирования (1119744) страница 62019-05-09СтудИзба
Просмтор этого файла доступен только зарегистрированным пользователям. Но у нас супер быстрая регистрация: достаточно только электронной почты!

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

catch (тип1 параметр) { ... }

catch (тип2 параметр) { ... }

Сначала мы входим в try, как будто его и нет вовсе. Если вдруг мы попадаем на инструкцию throw, то код ниже неё не выполняется, а управление передаётся. Среди параметров catch ищем подходящий тип исключения. Если находим, то выполняются действия в нём. Там может быть любой код, можно также использовать значение параметра. Когда инструкции выполнятся, переходим на оператор после последнего catch.

Обработчики могут быть трёх видов:

  • catch (тип параметр) { ... }

  • catch (тип) { ... } // не интересно значение параметра

  • catch (...) { ... } // обрабатывает любое исключение

Обработчик исключения catch типа T может обработать исключение типа E, если:

  • T и E одного и того же типа (с точностью до typedef)

  • T однозначный и доступный базовый класс к E;

  • T, E – указатели, E может быть преобразован к T с помощью стандартных преобразований (указатель на производный класс приводится к указателю на однозначный доступный базовый класс, любой указатель приводится к void* ; здесь 0 не преобразуется к NULL)

Вместо T также могут появиться const T, T&, const T&.

Важен порядок, в котором перечислены обработчики обработчики:

catch (void *) { ... } // все указатели попадут сюда

catch (char *) { ... } // так что этот обработчик не работает

catch (...) { ... }

catch (тип) { ... } // а до этого обработчика не доберется

// вообще ни одно исключение

Вызов throw; в catch-блоке позволяет передать обработку исключения в об’емлющий try-блок с тем же параметром.

Действия при возбуждении исключения throw x:

  1. Создаётся временный об’ект – копия x, это ещё одна ситуация, когда вызывается конструктор копирования (если, конечно, x – это объект пользовательского класса).

  2. Для всех других об’ектов из try-блока освобождается память и вызываются деструкторы (на самом деле, то же самое происходит при выходе по goto), для всех созданных подоб’ектов делается то же самое, процесс называется свёрткой стека или раскруткой стека (stack unwinding).

  3. Если найден подходящий catch-обработчик, выполняется его составной оператор, затем выполнение продолжается с оператора после последнего catch.

  4. Если нет подходящего обработчика, то работает принцип динамической ловушки: поиск продолжается в об’емлющем try-блоке. Если и там ничего не нашлось, мы возвращаемся в точку вызова функции и ищем try-блоки дальше.

  5. Если мы находим подходящий обработчик, то, после выполнения его кода, управление передаётся на оператор, следующий после серии catch, в которую входит отработавший обработчик.

  6. Если и в функции main() не нашлось подходящего обработчика, то вызывается функция terminate(), прекращающая выполнение программы.



Функция terminate()

Она вызывается, если:

  • нет подходящего обработчика исключения;

  • если деструктор в процессе свёртки стека возбудил исключительную ситуацию

  • при вызове throw; не в catch-блоке и не в функции, вызванной из него (т.е. если нет активного (обрабатываемого) исключения);

  • если стек разрушился.

Функцию terminate() можно переопределить:

set_terminate(handler);



Перевозбуждение исключений

try { throw x; }

catch (___) { throw; }

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

Пример.

class Vect {

int *p, size;

public:

Vect (int n = 10);

Vect (const Vect &a);

~Vect();

int &operator[] (int i);

};

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

Vect::Vect (int n){

if (n<=0) throw n;

p = new int [size = n];

/* если оператор new выполняется ошибочно, стандарт предписывает ему возбуждать исключение bad_alloc. Однако старые компиляторы просто возвращают NULL. Поэтому стандарт также рекомендует это делать в целях совместимости. */

if (!p) throw “Свободная память исчерпана”;

}

int &Vect::operator[] (int i){

if (i<0 || i>=size) throw “ошибочный индекс”;

return p[i];

}

void g (int k){

try {

Vect x(k);

int l, i;

l = x[10]; x[i] = 100;}

catch (int n){ cout<<”Неверный размер ”<<n<<endl; throw;}

catch (const char *str) {cout<<str<<endl; }

}

// предполагается, что функция, вызывающая g(), способна

// корректно обработать исключение типа int



Спецификация исключений

Мы не всегда пишем код с нуля. В библиотечных классах тоже есть исключения.

void f() throw (X,int) { ... }

Такая спецификация означает, что функция может вызывать throw X, throw int (на самом деле, может и throw Y, если X – однозначный доступный базовый класс для Y; то же справедливо и для указателей)

void f() throw () { ... }

А это значит, что функция не должна возбуждать исключений совсем.

По умолчанию функция может возбуждать любое исключение. Если функция попытается возбудить исключение, которого возбуждать не должна (контроль осуществляется исключительно во время работы программы!), вызывается функция unexpected(), прекращающая выполнение программы. Её также можно переопределить:

set_unexpected(handle);

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

Перегрузка функций.

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

Проблема поиска подходящей перегруженной функции (best matching) – нетривиальная задача. Для начала опишем этот алгоритм для функции одного аргумента.

  1. Поиск функции, точно совпадающей по типу параметра (точное отождествление). Если функция вызывается от параметра типа T, то может быть вызвано описание с прототипом от T, T&, const T, const T&, переопределения этих типов с помощью typedef, T[] эквивалентно T*, функция эквивалентна указателю на функцию.

  2. Если не найдено точное соответствие, то пробуем применить стандартные преобразования. На втором шаге могут сработать безопасные преобразования – целочисленное или вещественное расширение (integral/floating promotion). Тут bool, char, short, enum (знаковые или беззнаковые) преобразуются к int(если возможно) или unsigned, float преобразуется к double.

  3. Если не получилось выполнить шаг 2, пробуем все остальные стандартные преобразования: оставшиеся арифметические преобразования и преобразования указателей и ссылок (указатель на производный класс приводится к указателю на однозначный доступный базовый класс, любой указатель приводится к void*, 0 приводится к NULL).

  4. Пользовательские преобразования - рассматриваются конструкторы, которые могут быть вызваны с одним параметром. Также рассматриваются специальные функции преобразования типов. При выполнении пользовательского преобразования можно сделать еще одно (!) преобразование, но только с шага 2 или 3.

  5. Если ничего не помогло, придётся вызывать функцию с ‘…’.

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

Рассмотрим ряд примеров.

Пример на 2-й шаг:

void f(int);

void f(double);

void g() {

short a=1;

float ff=1.0;

f(a); // f(int) // 2-й шаг

f(ff); // f(double) // 2-й шаг

}

Пример на 3-й шаг:

void f(char);

void f(double);

void g() {

f(1); // ошибка: неоднозначность

(две возможности на 3-м шаге)

}

Пример на 4-й шаг:

struct S{

S(long); // long -> S

operator int(); // S -> int

};

void f(long);

void f(char *);

void g(S);

void g(char *);

void ex(S &a){

f(a); // f((long)(a.operator int()))

g(1); // g(S((long)(1))

g(0); // g((char *)0) – 3-й шаг!

}

Особенности четвёртого шага:

1. Отсутствие транзитивности пользовательских преобразований. То есть, за один раз не может выполниться более одного преобразования типа.

class X { public: operator int(); ... };

class Y { public: operator X(); ... };

void f(){ Y a; int b; ...

b = a; // нельзя

}

Можно явно указать b = a.operator X().operator int();.

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

class B {

public: B (int i);

operator int();

B operator+ (int B);

};

void f(){

B l(1); ... l+1 ...

}

Возникает неоднозначность: то ли l стоит преобразовать к int с помощью определённого преобразования и складывать числа, то ли вызвать конструктор от int и складывать об’екты типа B.

3. Конструктор должен быть описан так, чтобы он допускал неявный вызов. То есть, конструктор не может быть описан как explicit.

class X { public: X(int); };

X a(1); X b = 2; // так можно

Теперь изменим об’явление:

class X { public: explicit X(int); };

X a(1); // так можно

X b = 2; // так нельзя!

X с = X(2); // так можно

Зачем же нужна такая конструкция? Вспомним наш класс String.

class String { String (int n); ... };

String s1 = 10; // выделится память под строку из 10 символов

String s2 = ‘a’; // неужели мы хотим выделить память

// под строку из код('a') символов?!

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

Алгоритм поиска наилучшего соответствия для вызова функции с произвольным числом параметров N:

  1. По каждому из параметров ищется best matching по пятишаговому алгоритму за тем исключением, что если на каком-то шаге несколько кандидатов, способных обслужить вызов, запоминаем все их. В итоге получаем N множеств возможных функций.

  2. Ищем пересечение этих множеств. Если оно пусто, то нет подходящей функции. Если пересечение содержит 2 или более элемента, то неоднозначность. Но если там одна функция, она и обслужит вызов.

Пример.

class X { public: X (int); ... };

class Y { ... };

void f (X, int); /* 1 */

void f (X, double); /* 2 */

void f (Y, double); /* 3 */

Пусть мы вызываем f(1,5);. По первому параметру мы оставляем 1 и 2 (пользовательские преобразования), по второму – 1 (точное соответствие). Пересечение даёт первый вариант.

Теперь попробуем вызвать f(1,5.0);. По первому параметру мы оставляем 1 и 2 (пользовательские преобразования), по второму – 2 и 3 (точное соответствие). Пересечение даёт второй вариант.

Пример на *пятый шаг*.

class R { public: R (double); ... };

void f (int, R);

void f (int, ...);

void g () {

f (1, 1); // первый обработчик

f (1, “preved!”); // второй обработчик

}

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

Список файлов ответов (шпаргалок)

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