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

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

Страниц: 1 ... 3 4 [5]   Вниз
  Печать  
Автор Тема: C++ Exceptions и Qt  (Прочитано 34381 раз)
navrocky
Гипер активный житель
*****
Offline Offline

Сообщений: 817


Погроммист


Просмотр профиля
« Ответ #60 : Апрель 19, 2012, 14:39 »

Посмотрите что стоит в catch в исходнике exec которые привел Akon. Чудесная "раскрутка" почему-то не сделала (пере)установку inExec и loopLevel, и приложение рухнет если убрать это из catch.
Не вижу ничего подозрительного, все откатывается корректно в catch.

Цитировать
Также заметим что с пере-испусканием throw утеряна вся информация об исключении.
Ну что вы. Откуда такая информация?
Записан

Гугль в помощь
Bepec
Гость
« Ответ #61 : Апрель 19, 2012, 14:50 »

А да, интересный вопрос.

Если при раскрутке стека, произошла ещё парочка исключений, куда они денутся?

т.е. например:

валидация в диалог -> ексепшн "валид Еррор"
виджет главного окна -> ексепшн "выход за пределы массива"
менеджер окон -> ексепшн "порча памяти"
и наконец вываливается это всё к обработчику, но.... Но что придёт в конце? Показает язык

Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #62 : Апрель 19, 2012, 15:30 »

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

Цитировать
Также заметим что с пере-испусканием throw утеряна вся информация об исключении.
Ну что вы. Откуда такая информация?
Из приведенных исходников. Если хочу поставить обработчик выше exec, то смогу ловить только catch (...) + буду утыкан Qt сообщениями  Улыбающийся
Записан
iroln
Гость
« Ответ #63 : Апрель 19, 2012, 16:01 »

Цитировать
1. Хоть сколько нибудь серьезная программа никогда не будет размещать бизнес логику (Validate) в слое GUI.
А логика и gui в Qt разбиты на ui класса и, собственно, сам класс. Почитайте что-ли книжки, а?
Так-то оно так, но как не выкорячивайся, всё равно в "собственно самом классе" вам всё равно придётся дёргать gui-объекты - это, как пример, поставить новый текст в лэйбл, опросить состояние комбобокса, зажигать/гасить виджеты и т.п. В итоге получается каша, как не крути. А пляска с setEnabled - это вообще застрелиться. Если вот это так, а это так, а то эдак, значит эту кнопку погасить, ту зажечь, а тут стало работать неправильно, забыли, что там ещё что-то влияет на текущее состояние и понеслась... всё это превращается в трудноразбираемую лапшу в геометрической прогрессии, в итоге всё выкидывается и пишется заново с навороченными менеджерами состояний, шаблоне на шаблоне на шаблоне и т.д. Ненавижу.  Обеспокоенный

По поводу исключений, вон в питоне они везде используются и ничего, всё ок. Даже итераторы бросают исключение при завершении. try/finally и менеджеры управления контекстом позволяют не испытывать головную боль при использовании исключений. В С++ конечно с исключениями посложнее, поэтому многие от них отказываются. У нас в проектах на С++ запрещены исключения.
Записан
silart
Гость
« Ответ #64 : Апрель 19, 2012, 17:57 »

Да и действительно, приведите пожалуйста свой код "среднего" try/catch в ваших программах. Хочется оценить величину простыни и понятность кода.

Привожу:

Сам класс исключений:
Код:
	class Exception : public boost::exception
{
public:
std::string title() const;
std::string message() const;
long code() const;
std::string function() const;
std::string file() const;
int line() const;

std::string what() const;
};

#define ML_ASSERT(exp) ((exp)? ((void)0): ml::AssertionFailed("Ошибка времени выполнения", #exp, BOOST_CURRENT_FUNCTION, __FILE__, __LINE__))

#define ML_THROW(msg) throw ml::Exception() \
<< ml::__title__("Ошибка времени выполнения") \
<< ml::__message__(msg) \
<< ml::__function__(BOOST_CURRENT_FUNCTION) \
<< ml::__file__(__FILE__) \
<< ml::__line__(__LINE__)

ML_THROW, ML_ASSERT - это макросы, упрощающие генерацию исключений.

Вот небольшой класс, который бросает исключения:
Код:
	class Reader : public boost::noncopyable
{
private:
bifstream m_fileStream; ///< Файловый поток
std::vector<Point> m_points; ///< Буфер прочитанных значений
std::string m_caption; ///< Название
unsigned int m_channels; ///< Число каналов
unsigned int m_frequency; ///< Частота

private:
void readHeader();
void readPoints();

public:
Reader(const boost::filesystem::path& filename);
std::string caption() const;
unsigned int channels() const;
unsigned int frequency() const;
size_t size() const;

std::vector<Point> read(size_t base, size_t num);
std::vector<double> read(size_t base, size_t num, unsigned int channel);

Point operator[](size_t index) const;
};

Часть реализации вышеприведенного класса:
Код:
std::vector<Point> Reader::read(size_t base, size_t num)
{
using namespace std;

vector<Point> result;

if (base >= 0 && base < m_points.size() && (base + num) <= m_points.size())
{
result.reserve( num );

copy(m_points.begin() + base,
m_points.begin() + base + num,
back_inserter(result));
}
else
{
boost::format msg("illegal read interval: \"[%1%; %2%]\"");
msg % base % (base + num);
ML_THROW(msg.str());
}

return result;
}

std::vector<double> Reader::read(size_t base, size_t num, unsigned int channel)
{
using namespace std;
using namespace boost::phoenix;

vector<double> result;

if (channel >= channels() )
{
boost::format msg("channel value \"%1%\" is not correct. Channels number: \"[%2%\"");
msg % channel % channels();
ML_THROW(msg.str());
}

if (base < 0 || base >= m_points.size() || (base + num) > m_points.size())
{
boost::format msg("illegal read interval: \"[%1%; %2%]\"");
msg % base % (base + num);
ML_THROW(msg.str());
}

result.reserve(num);

transform(m_points.begin() + base, m_points.begin() + base + num, back_inserter(result),
boost::phoenix::bind<double>(&Point::operator[], _1, channel));

return result;
}

Point Reader::operator[](size_t index) const
{
if (index > m_points.size() - 1)
{
boost::format msg("index value \"%1%\" out of range: \"[%2%; %3%]\"");
msg % index % 0 % (m_points.size() - 1);
ML_THROW(msg.str());
}

return m_points[index];
}
Обратите внимание как бросаются исключения.

А вот класс, который использует Reader и обрабатывает его исключения:
Код:
class PlayerWD : public InternalWD
{
friend class AbstractWD;

osc::ReadStream m_stream; ///< Поток для чтения
boost::shared_ptr<ml::thread> m_thread; ///< Внутренний поток
double m_frequency; ///< Частота следования измеренных значений из файла
Buffer m_buffer; ///< Буфер последних значений
bool fIsEof; ///< Флаг конца файла
bool fIsFailed; ///< Флаг ошибки

private:
void routine();

private:
PlayerWD(const std::string& filename);

public:
~PlayerWD();

AbstractWD::Sample Weight();
};

А вот как происходит обработка исключений, сгенерированных где-то в глубине класса Reader.
Код:
PlayerWD::PlayerWD(const std::string& filename) : 
m_buffer(SAMPLE_BUFFER_SIZE), m_frequency(0), fIsEof(false), fIsFailed(false)
{
using namespace boost;
using namespace boost::filesystem;

path p(filename);

shared_ptr<osc::Reader> reader(new osc::Reader( p ));
m_stream.setReader(reader);
m_frequency = reader->frequency();

if (m_frequency == 0)
ML_TITLE_THROW(MSG__PLAYERWD_ERROR, "Invalid file");

// Запускаем цикл выборки значений из файла
m_thread.reset( new ml::thread(boost::bind(&PlayerWD::routine, this)) );
m_thread->start();
}

void PlayerWD::routine()
{
try
{
Sample s;

m_stream >> s;

m_buffer.put( s );
}
catch(osc::eof&)
{
fIsEof = true;

// Помещаем в буфер пустой сэмпл
// Нужно чтобы выпустить клиентский поток,
// читающий в данный момент из буфера, если буфер пуст
m_buffer.put( Sample() );

m_thread->stop();
}
catch (ml::Exception& e)
{
// Проблема копирования считанного значения в селектор
fIsFailed = true;
Log::out() << e.what() << endl;

// Помещаем в буфер пустой сэмпл
// Нужно чтобы выпустить клиентский поток,
// читающий в данный момент из буфера, если буфер пуст
m_buffer.put( Sample() );

m_thread->stop();
}

// Выдавать измерения нужно с заданной частотой
sleep_us( int(1000 / m_frequency) );
}

Поясняю, класс PlayerWD в отдельном потоке циклически опрашивает класс ReadStream (это функция routine() ), который обращается к классу Reader.

« Последнее редактирование: Апрель 19, 2012, 18:03 от silart » Записан
Bepec
Гость
« Ответ #65 : Апрель 20, 2012, 06:58 »

И после этого вам не кажется такое количества кода излишним? Улыбающийся

Тут и на 3 простыни хватит, если не на 5.
Записан
silart
Гость
« Ответ #66 : Апрель 20, 2012, 08:05 »

И после этого вам не кажется такое количества кода излишним? Улыбающийся

Тут и на 3 простыни хватит, если не на 5.

Верес, важно не количество, а качество!  Улыбающийся
Просто довольно сложный проект. Я вам хотел показать каким образом у меня происходит генерирование и обработка исключений.
Записан
Bepec
Гость
« Ответ #67 : Апрель 20, 2012, 08:12 »

Ну тут я увидел только вывод исключения, которое используется как сигнал куте.

И используется не в куте, а бусте. Зачем мешать сладкое с холодным???

Непоняяяяятно.

PS конечн интересно рассуждать о Qt и исключениях, думать при этом о программах на бусте, и в примерах приводить буст. Финита ля пародиа.
Записан
Страниц: 1 ... 3 4 [5]   Вверх
  Печать  
 
Перейти в:  


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