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

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

Страниц: [1] 2 3 ... 5   Вниз
  Печать  
Автор Тема: Стратегия обработки ошибок пользователя с помощью собственных классов исключений  (Прочитано 54004 раз)
8Observer8
Гость
« : Октябрь 18, 2014, 11:17 »

Привет!

Об этой стратегии обработки ошибок пользователя я прочитал в книге Professional C++ (2nd Edition) Скачать книгу (99МБ)+код к книге (464КБ) одним архивом (90МБ): https://yadi.sk/d/VCvsky11c6wtP Подробное описание создания собственных классов исключений находится здесь: "Chapter 10. Handling Errors" -> "Exceptions and Polymorphism" -> "Writing Your Own Exception Classes"

Проверка: непустой ли входной аргумент

Функция printArray принимает массив и выбрасывает исключение EmptyError, если входной аргумент пуст:

Output:
Цитировать
Error: empty argument in the function printArray()

main.cpp
Код
C++ (Qt)
#include <vector>
#include <iostream>
#include "freeFunctions.h"
 
int main()
{
   std::vector<int> arr;
 
   try {
       printArray( arr );
   } catch ( const LogicError &e ) {
       std::cerr << e.what() << std::endl;
       return 1;
   } catch ( ... ) {
       std::cerr << "Error: unknown expection" << std::endl;
       return 1;
   }
 
   return 0;
}
 

freeFunctions.h
Код
C++ (Qt)
#ifndef FREEFUNCTIONS_H
#define FREEFUNCTIONS_H
 
#include <vector>
#include <iostream>
#include "EmptyArgument.h"
 
void printArray( const std::vector<int> &arr )
throw ( EmptyArgument );
 
#endif // FREEFUNCTIONS_H
 

freeFunctions.cpp
Код
C++ (Qt)
#include "freeFunctions.h"
 
void printArray( const std::vector<int> &arr )
   throw ( EmptyArgument )
{
   std::string functionName = "printArray()";
 
   if ( arr.empty( ) ) {
       throw EmptyArgument( functionName );
   }
 
   for ( std::size_t i = 0; i < arr.size(); ++i ) {
       std::cout << arr[i] << std::endl;
   }
}
 

EmptyArgument.h
Код
C++ (Qt)
#ifndef EMPTYARGUMENT_H
#define EMPTYARGUMENT_H
 
#include <string>
#include "LogicError.h"
 
class EmptyArgument : public LogicError
{
public:
   EmptyArgument( const std::string &functionName ) :
       LogicError( functionName )
   {
       m_message = "Error: empty argument in the "
               "function " + m_functionName;
   }
};
 
#endif // EMPTYARGUMENT_H
 

LogicError.h
Код
C++ (Qt)
#ifndef LOGICERROR_H
#define LOGICERROR_H
 
#include <string>
#include <stdexcept>
 
class LogicError : public std::logic_error
{
public:
 
   LogicError( const std::string &functionName ) :
       std::logic_error( "" ),
       m_functionName( functionName ),
       m_message( "" )
   {
 
   }
 
   virtual ~LogicError( ) throw( )
   {
 
   }
 
   virtual const char *what( ) const throw( )
   {
       return m_message.c_str( );
   }
 
   std::string message( ) const
   {
       return m_message;
   }
 
protected:
   std::string m_functionName;
   std::string m_message;
};
 
#endif // LOGICERROR_H
 

Проверки: открыт ли файл, удачна ли запись, удачно ли чтение

Если файл не открывается, то выбрасывается исключение FileOpenError с текстом, к примеру:
Цитировать
Error: unable to open the file "input.txt" in the "readData()"

Если из файла невозможно прочитать, то - FileReadError с тектом:
Цитировать
Error: unable to read the file "input.txt" in the "readData()"

Если диск переполнен и невозможно записать, то - FileWriteError с текстом:
Цитировать
Error: unable to write to the file "input.txt" in the "readData()"

Все выше перечисленные исключения наследуются от FileError, поэтому мы можем все три исключения отлавливать так:
Код
C++ (Qt)
   try {
       // ...
   }
   catch ( const FileError &e ) {
       std::cerr << e.what( ) << std::endl;
       return 1;
   } catch ( ... ) {
       std::cerr << "Error: unknown exception" << std::endl;
       return 1;
   }
 

Исключение EmptyArgument выбрасывается, когда входные данные пустые и наследуется от LogicError

Следующий пример читает имена и фамилии из файла, заполняет массив объектов типа Person и выводит имена на экран:

main.cpp
Код
C++ (Qt)
#include <iostream>
#include <vector>
#include <QString>
#include "freeFunctions.h"
#include "Person.h"
 
int main( )
{
   // Person array for saving
   Person david( "David", "White");
   Person ivan( "Ivan", "Green" );
   std::vector<Person> persons;
   persons.push_back( david );
   persons.push_back( ivan );
 
   try {
       // Parse the person array to the string content
       QString content;
       parsePersonsToStrContent( persons, content );
 
       // Save the string content to the file
       QString fileName = "file.txt";
       writeData( fileName, content );
 
       // Read the string content from the file
       QString readContent;
       readData( fileName, readContent );
 
       // Parse the string content to the person array
       std::vector<Person> readPersons;
       parseContentToPersons( readContent, readPersons );
 
       // Print the person array on the screen
       printData( readPersons );
   } catch ( const LogicError &e ) {
       std::cerr << e.what( ) << std::endl;
       return 1;
   } catch ( const FileError &e ) {
       std::cerr << e.what( ) << std::endl;
       return 1;
   } catch ( ... ) {
       std::cerr << "Error: unknown exception" << std::endl;
       return 1;
   }
 
   return 0;
}
 

Person.h
Код
C++ (Qt)
#ifndef PERSON_H
#define PERSON_H
 
#include <QString>
 
class Person {
public:
 
   Person( const QString &firstName = "",
           const QString &lastName = "" ) :
       m_firstName( firstName ),
       m_lastName( lastName )
   {
 
   }
 
   QString firstName( ) const
   {
       return m_firstName;
   }
 
   QString lastName( ) const
   {
       return m_lastName;
   }
 
   void setFirstName( const QString &firstName )
   {
       m_firstName = firstName;
   }
 
   void setLastName( const QString &lastName )
   {
       m_lastName = lastName;
   }
 
private:
   QString m_firstName;
   QString m_lastName;
};
 
#endif // PERSON_H
 

freeFunctions.h
Код
C++ (Qt)
#ifndef FREEFUNCTIONS_H
#define FREEFUNCTIONS_H
 
#include <vector>
 
#include <QString>
 
#include "FileOpenError.h"
#include "FileReadError.h"
#include "FileWriteError.h"
#include "EmptyArgument.h"
#include "Person.h"
 
void readData( const QString &fileName, QString &content )
throw ( EmptyArgument, FileOpenError, FileReadError );
 
void parseContentToPersons( const QString &content,
                           std::vector<Person> &persons )
throw ( EmptyArgument );
 
void parsePersonsToStrContent( const std::vector<Person> &persons,
                              QString &content)
throw ( EmptyArgument );
 
void writeData( const QString &fileName,
               const QString &content )
throw ( EmptyArgument, FileOpenError, FileWriteError );
 
void printData( const std::vector<Person> &persons )
throw ( EmptyArgument );
 
#endif // FREEFUNCTIONS_H
 

freeFunctions.cpp
Код
C++ (Qt)
#include <iostream>
#include <string>
#include <QFile>
#include <QRegExp>
#include <QTextStream>
#include <QDebug>
#include "freeFunctions.h"
 
void readData(const QString &fileName, QString &content )
throw ( EmptyArgument, FileOpenError, FileReadError )
{
   std::string functionName = "readData()";
 
   // Check argument
   if ( fileName.isEmpty( ) ) {
       throw EmptyArgument( functionName );
   }
 
   // Open the input file for reading
   QFile file( fileName );
   if( !file.open( QIODevice::ReadOnly ) ) {
       throw FileOpenError( fileName.toStdString( ), functionName );
   }
 
   // Read the content from the file
   QByteArray data = file.readAll( );
   if ( data.isEmpty( ) ) {
       throw FileReadError( fileName.toStdString( ), functionName );
   }
 
   content = QString( data );
}
 
void parseContentToPersons( const QString &content, std::vector<Person> &persons )
throw ( EmptyArgument )
{
   std::string functionName = "parseContentToPersons()";
 
   // Check the input argument
   if ( content.isEmpty( ) ) {
       throw EmptyArgument( functionName );
   }
 
   QRegExp regExp("(\\w+) (\\w+)");
   int pos = 0;
   while ( ( pos = regExp.indexIn( content, pos ) ) != -1 ) {
       QString firstName = regExp.cap( 1 );
       QString lastName = regExp.cap( 2 );
       Person person( firstName, lastName );
       persons.push_back( person );
       pos += regExp.matchedLength( );
   }
}
 
void parsePersonsToStrContent( const std::vector<Person> &persons,
                              QString &content)
throw ( EmptyArgument )
{
   std::string functionName = "parsePersonsToStrContent()";
 
   // Check the input argument
   if ( persons.empty( ) ) {
       throw EmptyArgument( functionName );
   }
 
   for ( std::size_t i = 0; i < persons.size( ); ++i ) {
       QString firstName = persons[i].firstName( );
       QString lastName = persons[i].lastName( );
       QString line = QString( "%1 %2\n" ).arg( firstName ).arg( lastName );
       content.append( line );
   }
}
 
void writeData( const QString &fileName, const QString &content )
throw ( EmptyArgument, FileOpenError, FileWriteError )
{
   std::string functionName = "writeData()";
 
   // Check arguments
   if ( fileName.isEmpty( ) || content.isEmpty( ) ) {
       throw EmptyArgument( functionName );
   }
 
   // Open the output file for writing
   QFile file( fileName );
   if ( !( file.open( QIODevice::WriteOnly ) ) ) {
       throw FileOpenError( fileName.toStdString( ), functionName );
   }
 
   // Write data to the output file
   QTextStream stream( &file );
   stream << content;
   if ( stream.status() != QTextStream::Ok ) {
       throw FileWriteError( fileName.toStdString( ), functionName );
   }
}
 
void printData( const std::vector<Person> &persons )
throw ( EmptyArgument )
{
   std::string functionName = "printData()";
 
   // Check the input argument
   if ( persons.empty( ) ) {
       throw EmptyArgument( functionName );
   }
 
   // Print data
   for ( std::size_t i = 0; i < persons.size( ); ++i ) {
       std::cout << "First Name: " << persons[i].firstName( ).toStdString( ) << std::endl;
       std::cout << "Last Name: " << persons[i].lastName( ).toStdString( ) << std::endl;
       std::cout << std::endl;
   }
}
 

FileError.h
Код
C++ (Qt)
#ifndef FILEERROR_H
#define FILEERROR_H
 
#include <string>
#include <stdexcept>
 
class FileError : public std::runtime_error
{
public:
 
   FileError( const std::string &fileName,
              const std::string &functionName) :
       std::runtime_error( "" ),
       m_message( "" ),
       m_fileName( fileName ),
       m_functionName( functionName )
   {
 
   }
 
   virtual ~FileError( ) throw( )
   {
 
   }
 
   virtual const char *what() const throw( )
   {
       return m_message.c_str( );
   }
 
   std::string message( ) const
   {
       return m_message;
   }
 
protected:
   std::string m_message;
   std::string m_fileName;
   std::string m_functionName;
};
 
#endif // FILEERROR_H
 

FileOpenError.h
Код
C++ (Qt)
#ifndef FILEOPENERROR_H
#define FILEOPENERROR_H
 
#include <string>
#include "FileError.h"
 
class FileOpenError : public FileError {
public:
 
   FileOpenError( const std::string &fileName,
                  const std::string &functionName) :
       FileError( fileName, functionName )
   {
       m_message = "Error: unable to open the file \"" +
               m_fileName + "\" in the function \"" +
               m_functionName + "\"";
   }
};
 
#endif // FILEOPENERROR_H
 

FileReadError.h
Код
C++ (Qt)
#ifndef FILEREADERROR_H
#define FILEREADERROR_H
 
#include <string>
#include "FileError.h"
 
class FileReadError : public FileError {
public:
 
   FileReadError( const std::string &fileName,
                  const std::string &functionName ) :
       FileError( fileName, functionName )
   {
       m_message = "Error: unable to read the file \"" + m_fileName +
               "\" in the function \"" + m_functionName + "\"";
   }
};
 
#endif // FILEREADERROR_H
 

FileWriteError.h
Код
C++ (Qt)
#ifndef FILEWRITEERROR_H
#define FILEWRITEERROR_H
 
#include <string>
#include "FileError.h"
 
class FileWriteError : public FileError {
public:
 
   FileWriteError( const std::string &fileName,
                   const std::string &functionName ) :
       FileError( fileName, functionName )
   {
       m_message = "Error: unable to write to the file " +
               m_fileName + " in the function " + m_functionName;
   }
};
 
#endif // FILEWRITEERROR_H
 

EmptyArgument.h
Код
C++ (Qt)
#ifndef EMPTYARGUMENT_H
#define EMPTYARGUMENT_H
 
#include <string>
#include "LogicError.h"
 
class EmptyArgument : public LogicError {
public:
 
   EmptyArgument( const std::string &functionName ) :
       LogicError( functionName )
   {
       m_message = "Error: empty argument in the "
               "function " + m_functionName;
   }
};
 
#endif // EMPTYARGUMENT_H
 

LogicError.h
Код
C++ (Qt)
#ifndef LOGICERROR_H
#define LOGICERROR_H
 
#include <string>
#include <stdexcept>
 
class LogicError : public std::logic_error
{
public:
 
   LogicError( const std::string &functionName ) :
       std::logic_error( "" ),
       m_functionName( functionName ),
       m_message( "" )
   {
 
   }
 
   virtual ~LogicError( ) throw( )
   {
 
   }
 
   virtual const char *what( ) const throw( )
   {
       return m_message.c_str( );
   }
 
   std::string message( ) const
   {
       return m_message;
   }
 
protected:
   std::string m_functionName;
   std::string m_message;
};
 
#endif // LOGICERROR_H
 

Проверка деления на ноль и выхода из диапазона

В моём примере есть функция divide(a, b), где a и b должны быть в диапазоне [-1000, 1000]. Если один из параметров превысил этот диапазон, то функция выбросит исключение с текстом:
Цитировать
Error: values must be from the range [-1000, 1000] in the function Calculator::divide()

Допустим в моём проекте 10 классов, и в каждой по несколько функций, которые должны следить за диапазоном своих аргументов. Мне при написании этих функций достаточно выбросить после проверки исключение:
Код
C++ (Qt)
throw OutOfRange<int>( beginOfRange, endOfRange, functionName );

main.cpp
Код
C++ (Qt)
#include <iostream>
#include "Calculator.h"
 
int main()
{
   Calculator<float> calculator;
 
   try {
       float result = calculator.divide( 24.7f, 3.0f );
       std::cout << "Result = " << result << std::endl;
   } catch ( const LogicError &e ) {
       std::cerr << e.what() << std::endl;
       return 1;
   } catch ( ... ) {
       std::cerr << "Error: unknown expection" << std::endl;
       return 1;
   }
 
   return 0;
}

Calculator.h
Код
C++ (Qt)
#ifndef CALCULATOR_H
#define CALCULATOR_H
 
#include <string>
#include "DivideByZero.h"
#include "OutOfRange.h"
 
template <typename Type>
class Calculator
{
public:
   // Divide nums from the range [-1000, 1000]
   Type divide( Type a, Type b )
   throw ( DivideByZero, OutOfRange<int> )
   {
       std::string functionName = "Calculator::divide()";
       if ( b == 0 ) {
           throw DivideByZero( functionName );
       }
 
       const int beginOfRange = -1000;
       const int endOfRange = 1000;
 
       if ( ( a < beginOfRange ) || ( a > endOfRange ) ||
            ( b < beginOfRange ) || ( b > endOfRange ) )
       {
           throw OutOfRange<int>( beginOfRange,
                                  endOfRange,
                                  functionName );
       }
 
       return a / b;
   }
};
 
#endif // CALCULATOR_H

DivideByZero.h
Код
C++ (Qt)
#ifndef DIVIDEBYZERO_H
#define DIVIDEBYZERO_H
 
#include <string>
#include "LogicError.h"
 
class DivideByZero : public LogicError
{
public:
   DivideByZero( const std::string &functionName ) :
       LogicError( functionName )
   {
       m_message = "Error: divide by zero in the "
               "function " + m_functionName;
   }
};
 
#endif // DIVIDEBYZERO_H

OutOfRange.h
Код
C++ (Qt)
#ifndef OUTOFRANGE_H
#define OUTOFRANGE_H
 
#include <string>
#include "LogicError.h"
 
template <typename Type>
class OutOfRange : public LogicError
{
public:
   OutOfRange( Type beginOfRange,
               Type endOfRange,
               const std::string &functionName ) :
       LogicError( functionName )
   {
       m_message = "Error: values must be from the range "
                   "[" + std::to_string( beginOfRange ) +
                   ", " + std::to_string( endOfRange ) + "]"
                   " in the function " + m_functionName;
   }
};
 
#endif // OUTOFRANGE_H

LogicError.h
Код
C++ (Qt)
#ifndef LOGICERROR_H
#define LOGICERROR_H
 
#include <string>
#include <stdexcept>
 
class LogicError : public std::logic_error
{
public:
 
   LogicError( const std::string &functionName ) :
       std::logic_error( "" ),
       m_functionName( functionName ),
       m_message( "" )
   {
 
   }
 
   virtual ~LogicError( ) throw( )
   {
 
   }
 
   virtual const char *what( ) const throw( )
   {
       return m_message.c_str( );
   }
 
   std::string message( ) const
   {
       return m_message;
   }
 
protected:
   std::string m_functionName;
   std::string m_message;
};
 
#endif // LOGICERROR_H

Интересные ссылки:
Правило 8: Не позволяйте исключениям покидать деструкторы
Правило 25: Подумайте о поддержке функции swap, не возбуждающей исключений
Правило 29: Стремитесь, чтобы программа была безопасна относительно исключений
Exception Safety | QtDoc 5.3
« Последнее редактирование: Октябрь 21, 2014, 12:03 от 8Observer8 » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #1 : Октябрь 18, 2014, 12:00 »

Пару дней назад был такой случай: приложение виснет при испускании exception. Поставил печать в catch - до нее дело не доходит. Как такое может быть?
Записан
8Observer8
Гость
« Ответ #2 : Октябрь 18, 2014, 12:07 »

Пару дней назад был такой случай: приложение виснет при испускании exception. Поставил печать в catch - до нее дело не доходит. Как такое может быть?
Я лишь показал стратегию. Если есть предложения, замечания и т.д., то я могу внести исправления. Ваш вопрос не относится к теме. Создавайте свою. Если  относится, то не говорите загадками, а опишите проблему в моём примере, если она есть
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #3 : Октябрь 18, 2014, 12:28 »

Я лишь показал стратегию.
А может Вам лучше сначала набраться практического опыта, а потом уж пописывать статейки и "показывать стратегию"? Улыбающийся А то первый же простейший вопрос ставит "стратега" в тупик  Улыбающийся

Записан
8Observer8
Гость
« Ответ #4 : Октябрь 18, 2014, 13:02 »

Я не придумывал эту стратегию, а перетранслировал из книги. Использую её на практике. Написал здесь, чтобы услышать конструктивную критику и исправить недочёты в демо-примере

Цитировать
приложение виснет
Почему виснет, а не рушится?

Цитировать
А может Вам лучше сначала набраться практического опыта, а потом уж пописывать статейки и "показывать стратегию"?
Я так не считаю. Эта статья будет расти вместе со мной. И если кто-то решит воспользоваться этой версией подхода и столкнётся с проблемой, то сообщит в комментариях и я внесу соответсвующие изменения/дополнения
« Последнее редактирование: Октябрь 18, 2014, 13:05 от 8Observer8 » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #5 : Октябрь 18, 2014, 13:39 »

Почему виснет, а не рушится?
Ну так приложение не вылетает, ошибки краша нет. Останавливаюсь в отладчике - вижу какие-то потроха ntcore.dll (или др системного модуля - не суть), и это все. Откуда это взялось из моего  кода - хз. Вот я и говорю "виснет".

Вот допустим читал, читал и читал, (кстати вчера молодой человек наглядно показал знакомство с теми ссылками что выше). И тут хирак - вот такая ситуевина. Ну наверное если столько прочел, да еще и статью накатал - разрулит в момент! А иначе зачем читать, да еще и писать?  Улыбающийся
Записан
kambala
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4727



Просмотр профиля WWW
« Ответ #6 : Октябрь 18, 2014, 14:50 »

Я не придумывал эту стратегию, а перетранслировал из книги.
таким вещам место в уютненьком [бложике]
Записан

Изучением C++ вымощена дорога в Qt.

UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
8Observer8
Гость
« Ответ #7 : Октябрь 18, 2014, 18:50 »

Я не придумывал эту стратегию, а перетранслировал из книги.
таким вещам место в уютненьком [бложике]
Для того чтобы в бложике это кто-то причитал и это кому-нибудь пригодилось нужно время, так как его ещё нужно раскрутить. А здесь раздел подходящий и просмотров не мало. Я написал от средничка к начинающим и средничкам, чтобы вместе найти удобную стратегию контроля ошибок. Я развил идею из книги. Если хотя бы одному человеку это пригодится, то я буду рад. И ещё надеюсь на оценку этой стратегии от профессионалов, замечания, дополнения, критику и т.д. Этот подход, если не ошибаюсь, близок к подходу в C# и Java
« Последнее редактирование: Октябрь 18, 2014, 18:52 от 8Observer8 » Записан
Bepec
Гость
« Ответ #8 : Октябрь 18, 2014, 19:14 »

Это даже близко не статья. Просто сообщение.
Записан
8Observer8
Гость
« Ответ #9 : Октябрь 18, 2014, 20:09 »

Статья в коде
Записан
Nidxogg
Гость
« Ответ #10 : Октябрь 18, 2014, 20:44 »

Цитировать
Я развил идею из книги.
Каким образом?
Записан
Bepec
Гость
« Ответ #11 : Октябрь 18, 2014, 21:16 »

Тут нет развития. Тут нет даже пояснения. тут имеются ссылки на учебники и код... Печаль.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #12 : Октябрь 19, 2014, 10:21 »

Ладно, попробуем вникнуть в "перетранслированное"
Код
C++ (Qt)
   // Divide nums from the range [-1000, 1000]
   Type divide( Type a, Type b )
   throw ( DivideByZero, OutOfRange<int> )
   {
       std::string functionName = "Calculator::divide()";
       if ( b == 0 ) {
           throw DivideByZero( functionName );
       }
 
       const int beginOfRange = -1000;
       const int endOfRange = 1000;
 
       if ( ( a < beginOfRange ) || ( a > endOfRange ) ||
            ( b < beginOfRange ) || ( b > endOfRange ) )
       {
           throw OutOfRange<int>( beginOfRange,
                                  endOfRange,
                                  functionName );
       }
 
       return a / b;
   }
};
Я ненавижу такой код. Он создает дутый объем и впечатление "вумности", но реально за ним ничего нет. Откуда я возьму значения диапазона? Чего они вбиты как константы? Если мне надо поделить напр 2000 на 5, я что, уже не могу это сделать и всегда получу исключение? Какой вообще смысл в проверке делимого? И почему делитель проверяется на "слишком большое число" - что это за ошибка такая?

Как всегда в таких случаях насованы template, c претензией на общность. Но (как не всегда, но часто) общность эта липовая. Для чисел с точкой логика совсем другая.

Ах да, ну это же все "для примера". Мы же говорим о "стратегии", общем подходе. Так это тоже неверно, причем принципиально. Операции типа "деление на ноль" слишком мелки чтобы размазывать их в ф-цию, тем более они критичны по скорости (не надо парить про "преждевременную оптимизацию"). Правильно контролировать их прямо в коде, напр
Код
C++ (Qt)
if (b == 0) throw std::overflow_error("invalid b");  // все, с приветом, др разумной обработки нет
a /= b;
 
а часто и обходиться без исключений, особенно для чисел с точкой, напр
Код
C++ (Qt)
template <class T>
T ValidVal( T val, T minV = FUDGE_FACTOR )
{
if (unlikely(fabs(val)) < minV) return minV * (val < 0 ? -1 :  1);
return val;
}
...
a /= ValidVal(b);
Вот кстати типовая задача: есть ф-ция/метод нормализация вектора. Должна ли она бросать исключение?

Ладно, вернемся к нашему юному графоману Улыбающийся  8Observer8, у Вас есть свое видение проблемы, свой взгляд на вещи, основанный на личном опыте, которым Вы бы хотели поделиться? Я его в упор не вижу, Вы даже списываете совершенно бездарно. Если на Вас книга произвела неизгладимое впечатление - просто дайте ссылку на нее, не надо никаких статей.

Записан
8Observer8
Гость
« Ответ #13 : Октябрь 19, 2014, 16:41 »

Цитировать
Откуда я возьму значения диапазона?
Вы сами определяете диапазон и передаёте его исключению OutOfRange. Суть в том, что текст, который будет выводиться находится в OutOfRange. Это намного лучше того, если бы мы в каждой разрабатываемой функции кидали std::out_of_range( " Error: values must be from the range ... " ). Было бы дублирование текста. А свои классы исключений гибкие. Можно задавать параметры. Один из очень удобных параметров - это имя функции. И ещё раз отмечу централизованное управление выводимым текстом. Теперь можно писать свои классы исключений и наследовать их от LogicError. По-моему, очень даже удобно
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #14 : Октябрь 19, 2014, 17:18 »

Вы сами определяете диапазон и передаёте его исключению OutOfRange.
Каким образом я его определю Непонимающий Вот есть операция
Код
C++ (Qt)
a /= b;
Какие значения "а" можно делить на "b" а какие нельзя?
Записан
Страниц: [1] 2 3 ... 5   Вверх
  Печать  
 
Перейти в:  


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