Бьерн Страуструп.
Язык программирования С++
250
void f3(queue& q)
{
if (q.empty()) { // очередь пуста
//
...
}
else
{
message* m = q.get();
// используем m
}
}
Отметим, что вынести из функции get() проверку очереди на пустоту можно только при условии, что к
очереди нет параллельных обращений.
Не так то просто отказаться от взгляда, что обработка особой ситуации есть обработка ошибки. Пока
мы придерживаемся такой точки зрения, программа четко подразделяется на две части: обычная часть
и часть обработки ошибок. Такая программа более понятна. К сожалению, в реальных задачах провести
четкое разделение невозможно, поэтому структура программы должна (и будет) отражать этот факт.
Допустим, очередь бывает пустой только один раз (так может быть, если функция get() используется в
цикле, и пустота очереди говорит о конце цикла). Тогда пустота очереди не является чем-то странным
или ошибочным. Поэтому, используя для обозначения конца очереди особую ситуацию, мы расширяем
представление об особых ситуациях как ошибках. С другой стороны, действия, принимаемые в случае
пустой очереди, явно отличаются от действий, принимаемых в ходе цикла (т.е. в обычном случае).
Механизм особых ситуаций является менее структурированным, чем такие локальные структуры
управления как операторы if или for. Обычно он к тому же является не столь эффективным, если особая
ситуация действительно возникла. Поэтому особые ситуации следует использовать только в том
случае, когда нет хорошего решения с
более традиционными управляющими структурами, или оно,
вообще, невозможно. Например, в случае пустой очереди можно прекрасно использовать для
сигнализации об этом значение, а именно нулевое значение указателя на строку message, значит
особая ситуация здесь не нужна. Однако, если бы из
класса queue мы получали вместо указателя
значение типа int, то то могло не найтись такого значения, обозначающего пустую очередь. В таком
случае функция get() становится эквивалентной операции индексации из $$9.1, и более привлекательно
представлять пустую очередь с помощью особой ситуации. Последнее соображение подсказывает, что
в
самом общем шаблоне типа для очереди придется для обозначения пустой очереди использовать
особую ситуацию, а работающая с очередью функция будет такой:
void f(Queue
& q)
{
try
{
for (;;) {
// ``
бесконечный цикл''
// прерываемый особой ситуацией
X
m
=
q.get();
//
...
}
}
catch (Queue::Empty) {
return;
}
}
Если приведенный цикл выполняется тысячи раз, то он, по всей видимости, будет более эффективным,
чем обычный цикл с проверкой условия пустоты очереди. Если же он выполняется только несколько
раз, то обычный цикл почти наверняка эффективней.
В очереди общего вида особая ситуация используется как способ возврата из функции get().
Использование особых ситуаций как способа возврата может быть элегантным способом завершения
функций поиска. Особенно это подходит для рекурсивных функций поиска в дереве. Однако, применяя
особые ситуации для таких целей, легко перейти грань разумного и получить маловразумительную
программу. Все-таки всюду, где это действительно оправдано, надо придерживаться той точки зрения,
что обработка особой ситуации есть обработка ошибки. Обработка ошибок по самой своей природе
Бьерн Страуструп.
Язык программирования С++
251
занятие сложное, поэтому ценность имеют любые методы, которые дают ясное представление ошибок
в языке и
способ их обработки.
Достарыңызбен бөлісу: