Russian Qt Forum
Ноябрь 05, 2024, 22:06 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2 3 ... 5   Вниз
  Печать  
Автор Тема: C++ Exceptions и Qt  (Прочитано 34682 раз)
silart
Гость
« : Апрель 17, 2012, 05:44 »

Добрый день!

Товарищи! Кто-нибудь использует исключения С++ совместно с библиотекой Qt?

Ситуация такая: Есть некий диалог, который вызывается модально. На нем есть кнопки, поля ввода и другие виджеты. Диалог работает в соответствии со своей логикой. Таким образом, для диалога необходима проверка правильности ввода данных, заполнения полей, и т. д. Было бы очень удобно, если при нажатии на кнопку "ОК", в соответствующем слоте, бросались исключения, если пользователь сделал что-то неправильно:

Код:
void MyDialog::OnButtonOk()
{
    if (...) throw std::logic_error("some error");
}

А при вызове диалога использовалась такая конструкция:
Код:
try
{
   MyDialog dlg(this);
   dlg.exec();
}
catch(const std::exception& e)
{
// Вывод сообщения
}

Однако, такой подход неудобен тем, что при первом исключении сразу уничтожается объект диалога. Допустим пользователь забыл заполнить нужное поле, и после нажатия на "ОК", диалог уничтожится. Хотелось бы чтобы диалог не уничтожался, а выдавалось сообщение QMessageBox.
Очевидно, что для этого нужно установить try {} catch(...) внутри метода exec() где-то в теле цикла обработки сообщений.
Кто-нибудь задавался таким вопросом?

Записан
Bepec
Гость
« Ответ #1 : Апрель 17, 2012, 07:30 »

Зачем использовать исключения, если проще написать функцию проверки валидности?
И к примеру подсвечивать незаполненные важные поля, при преждевременном нажатии ОК?

PS исключения хорошо, но помоему не в этом случае.
Записан
silart
Гость
« Ответ #2 : Апрель 17, 2012, 08:01 »

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

Может у вас есть другой подход и вы знаете как избавиться от громоздко кода проверок?
Записан
Bepec
Гость
« Ответ #3 : Апрель 17, 2012, 08:09 »

Кхм... громоздкого? Ну незнаю.

Помоему, в любом случае этот код у вас будет. И проверяться на валидность будет одними и теми же методами. (вру, как минимум 3 способами я себе представляю)

И никуда этот код не денется, разницей будет только реакция - либо посылка исключения/неактивная кнопка "ОК"/мессага о невалидности введённой строки.

PS или я не вижу более очевидных методов проверки?
Записан
alexis031182
Гость
« Ответ #4 : Апрель 17, 2012, 08:12 »

Посмотрите QValidator. Как вариант.
Записан
silart
Гость
« Ответ #5 : Апрель 17, 2012, 08:28 »

Ну хорошо. А как вы обрабатываете ошибку возникшую в конструкторе диалога?
Хотя это другой случай.
Записан
Akon
Гость
« Ответ #6 : Апрель 17, 2012, 08:33 »

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

Не размещайте логику в интерфейсе! Представьте, что наряду с гуем есть параллельно, скажем, консольный интерфейс - сразу увидите дублирующийся код проверок.

В VCL удобная система в плане обработки ошибок через исключения - требует минимум усилий. Чтобы достичь такого же комфорта в Qt нужно переопределять QCoreApplication::notify() и патчить сорцы QtCore (QObjectPrivate::activate() если не ошибаюсь). Последнее особенно непрактично.


Цитировать
К тому же обработчик находится в одном месте и он всего один.
Можно использовать такой шаблон:
Код:
void MyDialog::OnOkButtonClick()
{
    QWidget* propertyControl = lineEdit1;
    try {
        businessLogic.setProperty1(lineEdit1->text());  // throws at error

        propertyControl = lineEdit2;
        businessLogic.setProperty2(lineEdit2->text());  // throws at error
        ....
    }
    catch (const BusinessLogicError& e) {
        QMessageBox::warning(... e.what() ...);
        propertyControl->setFocus();
    }
}

Иногда уставонка значений/проверки используются при потере фокуса элементом - это другой шаблон.
Записан
alexis031182
Гость
« Ответ #7 : Апрель 17, 2012, 08:52 »

Ну хорошо. А как вы обрабатываете ошибку возникшую в конструкторе диалога?
Хотя это другой случай.
В конструкторах должна быть лишь инициализация параметров класса значениями по умолчанию и/или на основе входных аргументов. Если требуется валидация входных аргументов, то лучше производить их внесение в класс в отдельной функции, типа

bool setParam(аргумент/список_аргументов);
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #8 : Апрель 17, 2012, 09:04 »

Однако, такой подход неудобен тем, что при первом исключении сразу уничтожается объект диалога.
Так можно и не уничтожать
Код
C++ (Qt)
MyDialog dlg(this);
while (true)
try
{
  dlg.exec();
  break;
}
catch(const std::exception& e)
{
// Вывод сообщения
}
}
 
Просто когда разрабатываешь диалог, слишком много получается кода, отвечающего за всякие проверки. И этот код очень трудно так структурировать, чтобы было все красиво и не было нагромождений.
Исключения, мне кажется, как раз бы уменьшили количество такого кода. К тому же обработчик находится в одном месте и он всего один.
Теория говорит что исключения не должны рассматриваться как альтернативный обработчик ошибок, а генерироваться только в том случае когда ситуация безвыходная, возможности обработки нет. Не очень верится что "ну очень трудно структурировать" в коде/методах диалога. Попытка сачкануть  Улыбающийся
Записан
Bepec
Гость
« Ответ #9 : Апрель 17, 2012, 09:22 »

Помоему это плохой тон - выводить исключения только при проверке параметров.

В VLC (могу и ошибаться) через исключения выводятся ошибки, приводящие в дальнейшем к крушению программы. К примеру кодека нету, но есть возможность (50 на 50), что запуститься и без него. Подмигивающий
Записан
Akon
Гость
« Ответ #10 : Апрель 17, 2012, 10:20 »

Цитировать
Теория говорит что исключения не должны рассматриваться как альтернативный обработчик ошибок, а генерироваться только в том случае когда ситуация безвыходная, возможности обработки нет.
Ой-ли, что за теория  Улыбающийся

Цитировать
Помоему это плохой тон - выводить исключения только при проверке параметров.

В VLC (могу и ошибаться) через исключения выводятся ошибки, приводящие в дальнейшем к крушению программы. К примеру кодека нету, но есть возможность (50 на 50), что запуститься и без него.
А если параметр проверяется в глубоко вложенной функции - че будете переть код возврата через все уровни? И на счет VCL вы глубоко ошибаетесь. Там даже есть специальное исключение EAbort - типа просто отмена и все.

На самом деле исключения в широком смысле дают альтернативное ветвление программы для ваших нужд (в более узком смысле - это обработка ошибок), которое упрощает программирование за счет четкого разделения основной и альтернативной логик. Если в определенном смысле привести аналогию - это как std::cout и std::cerr в плане разделения вывода. Вы, конечно, можете ошибки херачить в std::cout и долго их потом искать. Смешение основной логики и логики обработки ошибок снижает читабельность и даже быстродействие кода.
« Последнее редактирование: Апрель 17, 2012, 10:22 от Akon » Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


Просмотр профиля
« Ответ #11 : Апрель 17, 2012, 10:28 »

Цитировать
Теория говорит что исключения не должны рассматриваться как альтернативный обработчик ошибок, а генерироваться только в том случае когда ситуация безвыходная, возможности обработки нет.
Ой-ли, что за теория  Улыбающийся

Цитировать
Помоему это плохой тон - выводить исключения только при проверке параметров.

В VLC (могу и ошибаться) через исключения выводятся ошибки, приводящие в дальнейшем к крушению программы. К примеру кодека нету, но есть возможность (50 на 50), что запуститься и без него.
А если параметр проверяется в глубоко вложенной функции - че будете переть код возврата через все уровни? И на счет VCL вы глубоко ошибаетесь. Там даже есть специальное исключение EAbort - типа просто отмена и все.

На самом деле исключения в широком смысле дают альтернативное ветвление программы для ваших нужд (в более узком смысле - это обработка ошибок), которое упрощает программирование за счет четкого разделения основной и альтернативной логик. Если в определенном смысле привести аналогию - это как std::cout и std::cerr в плане разделения вывода. Вы, конечно, можете ошибки херачить в std::cout и долго их потом искать. Смешение основной логики и логики обработки ошибок снижает читабельность и даже быстродействие кода.
Тешьте себя, снижает, ага. А исключения не снижают.
Записан
Bepec
Гость
« Ответ #12 : Апрель 17, 2012, 10:40 »

К сожалению, Akon, использование исключений в таком качестве, не рекомендуется всеми более-менее значимыми величинами в ООП.

И я придерживаюсь их мнения. Да, их можно использовать - но если у вас обработка ошибки происходит в непонятных епенях, а код ошибки летит куда-то ближе к стратосфере - помоему это уже плохо.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #13 : Апрель 17, 2012, 11:03 »

Ой-ли, что за теория  Улыбающийся
Библия Стаутструпа
А если параметр проверяется в глубоко вложенной функции - че будете переть код возврата через все уровни?
Иногда приходится и переть. Конечно было бы здорово поставить где-то вверху catch чтобы сообщить "ах, извините, недостаточно памяти". Только не всегда удается так легко отделаться.

Проверка параметров никак не выглядит требующей исключений. Весь контекст/данные на руках, ну повыскакивал через return false - и все. Вероятно трудности с выводом сообщения об ошибке, точнее с его формированием. Это часто как бы "налипает" на каждую if проверку. Впрочем надо послушать автора темы, а то предположений можно сделать много.
Записан
Akon
Гость
« Ответ #14 : Апрель 17, 2012, 11:22 »

Цитировать
Тешьте себя, снижает, ага. А исключения не снижают.
Я ограничусь одним нетехническим аргументом: современные мейнстрим языки - какова роль исключений там? (Преобладающая).

Цитировать
К сожалению, Akon, использование исключений в таком качестве, не рекомендуется всеми более-менее значимыми величинами в ООП.

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

Цитировать
Библия Стаутструпа
Да ну? Насколько я помню, он там даже множественное наследование исключений пользует!

Цитировать
Теория говорит что исключения не должны рассматриваться как альтернативный обработчик ошибок
Полагаю, вы хотели сказать, что не все ситуации, ошибочные на первый взгляд, следует считать таковыми и, соответственно, использовать под них исключения.
Записан
Страниц: [1] 2 3 ... 5   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.098 секунд. Запросов: 23.