Правила программирования на Си и Си++



         

159. Назначение исключений — не быть пойманными - часть 2


значение NULL. По причинам, обсуждаемым позже, я не думаю, что исключение должно быть использовано вместо возврата ошибки просто для защиты программистов от себя самих, но оно срабатывает с new, потому что эта ошибка обычно в любом случае неисправима. Лучшим примером может быть функция printf(). Большинство программистов на Си даже не знают, что printf()

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

Итак, что же плохого в исключениях? На самом деле существует две проблемы. Первой является читаемость. Вам будет тяжело меня убедить, что:

some_class obj;

try

{

   obj.f();

}

catch( some_class::error &r )

{

   // выполнить действие в случае ошибки

}

лучше читается, чем:

if( obj.f() == ERROR )

// выполнить действие в случае ошибки

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

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

char  data[128];

Cfile f( "some_file", CFile::modeWrite );

try

{

   f.Write( data, sizeof(data) );

}

catch( CFileException &r )

{

   if( r.m_cause == CfileException::diskFull )

   // что-то сделать

}

Имеется две проблемы. Первая явно связана с уродливостью этого кода. Я бы гораздо охотнее написал:




Содержание  Назад  Вперед