LINUX.ORG.RU

[qt] каноническая обработка ошибок

 


0

1

Приветсвую тебя, о великий и ужастный ЛОР!

В ядре очень классная схема используется, с goto. Мне она понравилась. Стараюсь её использовать по мере надобности. Для сишных поделий - самое оно. Но вот в С++ конструктор то ничего не возвращает. Можно конечно сделать два уродских метода дополнительных init/deinit. Но это полный отстой. По-этому в конструкторах выбрасываю исключения.

Всё хорошо, пока не появились сигналы слоты. В Qt исключения использовать то можно, но через сигнал-слот они проходят только с применением грубого хака в QApplication. Не хочу так делать.

Собсвенно вопрос:
Допустим объект Аз генерил сигнал, подключеный к слоту в объекте Буки. Слот из Буки должен создать какую-то сущность, или просто что-то сделать, но возникает ошибка. Как объекту Бука сообщить объекту Аз об ошибке. Кроме как создавать ещё один сигнал-слот (типа connect(B, error(QString), A, onError(QString)) ничего в голову не приходит.

Как быть в общем случае? Спасибо.

Ответ на: комментарий от unC0Rr

Хотя оператор >>=, очевидно, ни к чему. Остаётся просто boost::variant в чистом виде.

unC0Rr ★★★★★
()

QSharedPointer или QVariant. Лучше дополнить тип, чем создавать новый слот.

dave ★★★★★
()
Ответ на: комментарий от nanoo_linux

В хаскеле Maybe имеет два конструктора: Nothing и Just a, где a - любой тип. Т.е. значение типа Maybe или пустое, или хранит в себе значение нужного тебе типа. Ситуация похожа на передачу ссылки на объект: если указатель нулевой, то ничего не передано, иначе это указатель на объект.

boost::variant позволяет хранить в себе значение одного из двух типов. Для реализации Maybe созданы классы Nothing и Just, при получении значения типа Maybe проверяется, можно ли получить из него указатель на Nothing, и если нет - значит там хранится значение класса Just, иначе - ничего.

unC0Rr ★★★★★
()
Ответ на: комментарий от dave

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

unC0Rr ★★★★★
()

Как вариант, возвращать объект-пустышку. Что-то вроде того, как сделано в самом кутэ для некоторых классов, у которых есть метод isValid().

rival ★★
()

Ну и, да, если возвращается указатель, то можно возвращать 0 в случае ошибки.

Кроме как создавать ещё один сигнал-слот (типа connect(B, error(QString), A, onError(QString)) ничего в голову не приходит.

И таки чем плох этот вариант?

rival ★★
()

>В Qt исключения использовать то можно

А вот и не всегда. Для QWS нельзя. И если писать код с учётом этой платформы, то видимо лучше обходиться без этого.

gogi
()

Странный вопрос:

можно через сигнал-слот; можно через вызов метода sender()-а можно через QApplication::postEvent() можно через указатель на A, который хранится где-нибудь еще итд

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

А по поводу эксепшенов: я обычно в объекте сразу создаю поле m_error, и если конструктор может повести себя неправильно, то заполняю этот m_error. После вызова делаю проверку пустая ли эта m_error, если да isValid() {return m_error.isEmpty()} - все ок; нет - сообщение об ошибке есть.

anonymous
()
Ответ на: комментарий от rival

Ничем не плох. Я просто думал, что может ещё какие варианты есть. Судя по всему так и придётся делать, только в аргументы надо добавить где ошибка. К сигналу ведь много слотов может быть подкючено. Тогда «сигнализирующему» объекту надо знать в каком именно слоте ошибка. Но это уже так, детали. Сам к себе придираюсь.

nanoo_linux
() автор топика
Ответ на: комментарий от anonymous

Я раньше тоже так делал. Но теперь придерживаюсь принципа «нет удачного вызова конструктора - нет объекта». Так логика проще получается. Иначе вам всё время надо будет этот m_error проверять.

nanoo_linux
() автор топика
Ответ на: комментарий от nanoo_linux

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

m0rph ★★★★★
()
Ответ на: комментарий от m0rph

программа обычно просто падает с сообщением об ошибке

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

тебя неправильно спроектировано взаимодействие объектов

Если бы у меня были лишь вызовы методов - то это не чем не отличалось бы от способа описного в первом абзаце темы. И вопроса бы и не возникало. А вопрос как раз в связке сигнал-слот. В доках пишут: это - сигналы, это - слоты. Коннект и... опа! - всё работает. А я спрашиваю как мне лучше уведомить «сигнализирующий» объект об ошибке в слоте? Или вообще стоит такое делать? Может существует другое решение?

nanoo_linux
() автор топика
Ответ на: комментарий от m0rph

если программист неправильно

опа. не вчитался.

тогда вопрос: програма создаёт объект, а он не создаётся. Например объект является соединением с www.linux.org.ru, а инета нет.

Как вы обработать эту ситуацию?

Я выброшу исключение, а в коде, который пытался это соединение создать, напишу try/catch. Думаю идея проста.

nanoo_linux
() автор топика
Ответ на: комментарий от namezys

Да, у меня плохо с ООП. Я и не претендую на то, что бы меня считали специалистом в этой области ;)

Ну а по делу есть что сказать?

nanoo_linux
() автор топика
Ответ на: комментарий от nanoo_linux

Ну это само собой, вобщем-то одной из причин, почему в C++ были введены исключения и является необходимость сообщить о невозможности создания объекта.

m0rph ★★★★★
()
Ответ на: комментарий от nanoo_linux

Есть. Не использовать этот механиз в том случае, если могут возникнуть такие ошибки

Сигналы/слоты это система уведомлений о событиях, а не способ запросить что либо

namezys ★★★★
()
Ответ на: комментарий от nanoo_linux

Это достаточно распространения точка зрения на этот механизм.

А то, что вы хотите, этим авторизовываться не должно

namezys ★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.