Наследование класса std::exception
От: Mak_71_rus Россия  
Дата: 01.07.10 17:39
Оценка:
Здравствуйте, форумчане!

Подскажите пожалуёста, если я создаю собственный класс ошибок, всегда ли он должен быть производным от std::exception?

Я решил написать класс rational, представляющий смешанное число. В результате сложения может призойти переполнение, или может быть попытка присвоить знаменателю нулевое значение — всё это исключительные ситуации. Я создал простую иерархию классов ошибок, базовый класс содержит только номер ошибки, а все производные — функцию-член, возвращающие этот номер. Мне кажется, такая система удобна в отладке, но стоит ли её оставлять как есть? Может лучше наследовать базовый класс от std::exceptin? Просто все строки, возвращаемые функцией what занимают места намного больше, чем сам экземпляр класса.



//Классы ошибок

//базовый класс для всех ошибок при действиях со смешанными числами
    class rational_exception
    {
    protected:
        unsigned short err_code;
    public:
        unsigned short get_err_code(){return err_code;}
    };

//базовый класс ошибок переполнения 
//(результат операции не может быть записан в unsigned long long)    
    class overflow : public rational_exception
    {
    };

//переполнение, возникшее в результате сложения двух чисел типа unsigned long long
    class addition_overflow : public overflow
    {
    public:
        addition_overflow(){err_code = 0;}
        explicit addition_overflow(unsigned char err_num){err_code = err_num;}
    };

//переполнение, возникшее в результате умножения двух чисел типа unsigned long long
    class multiplication_overflow : public overflow
    {
    public:
        multiplication_overflow(){err_code = 0;}
        explicit multiplication_overflow(unsigned char err_num){err_code = err_num;}
    };

//переполнение, возникшее в результате преобразования строки в чисело типа unsigned long long
    class recognition_overflow : public overflow
    {
    public:
        recognition_overflow(){err_code = 0;}
        explicit recognition_overflow(unsigned char err_num){err_code = err_num;}
    };

//базовый клас ошибок неверного ввода    
    class invalid_in : public rational_exception
    {
    };

//в результате операции ввода была попытка присвоить знаменателю 0    
    class null_denominator : public invalid_in
    {
    public:
        null_denominator(){err_code = 0;}
        explicit null_denominator(unsigned char err_num){err_code = err_num;}
    };

//ошибка ввода - введённая строка не может быть распознана как смешанное число    
    class is_not_rational_in : public invalid_in
    {
    public:
        is_not_rational_in(){err_code = 0;}
        explicit is_not_rational_in(unsigned char err_num){err_code = err_num;}
    };

    //базовый клас ошибок конструкторов    
    class invalid_constr_arg : public rational_exception
    {
    };

    //В конструктор передан 0 для присвоения знаменателю
       class null_denominator_in_constroctor : public invalid_constr_arg
    {
    public:
        null_denominator_in_constroctor(){err_code = 0;}
        explicit null_denominator_in_constroctor(unsigned char err_num){err_code = err_num;}
    };
Re: Наследование класса std::exception
От: wander  
Дата: 01.07.10 17:49
Оценка: 3 (2)
Здравствуйте, Mak_71_rus, Вы писали:

M__>Здравствуйте, форумчане!


M__>Подскажите пожалуёста, если я создаю собственный класс ошибок, всегда ли он должен быть производным от std::exception?


M__>Я решил написать класс rational, представляющий смешанное число. В результате сложения может призойти переполнение, или может быть попытка присвоить знаменателю нулевое значение — всё это исключительные ситуации. Я создал простую иерархию классов ошибок, базовый класс содержит только номер ошибки, а все производные — функцию-член, возвращающие этот номер. Мне кажется, такая система удобна в отладке, но стоит ли её оставлять как есть? Может лучше наследовать базовый класс от std::exceptin? Просто все строки, возвращаемые функцией what занимают места намного больше, чем сам экземпляр класса.


Мое мнение — наследовать нужно. Это считается хорошим тоном. Если вы пишете библиотеку, то такое поведение является естественно ожидаемым.
Re: Наследование класса std::exception
От: Mak_71_rus Россия  
Дата: 01.07.10 18:02
Оценка:
А такая иерархия ошибок не слишком сложна? Может просто оставить класс переполнения, неверного ввода и нулевого знаменателя (всего три вместо этой кучи)?
Re[2]: Наследование класса std::exception
От: kpcb Россия  
Дата: 01.07.10 18:48
Оценка: 2 (1)
Здравствуйте, Mak_71_rus, Вы писали:

M__>А такая иерархия ошибок не слишком сложна? Может просто оставить класс переполнения, неверного ввода и нулевого знаменателя (всего три вместо этой кучи)?


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

Наследовать от std::exception не обязательно. Но если унаследовать — то ловить потом будет проще


enum 
{
    kErrorAdditionOverflow,
    kErrorMultiplicationOwerflow,
    //.....
};

class rational_exception: public std::exception
{
public:
    explicit rational_exception(int k): code(k) {}
    int const code;
};

а ловить его так
try {
    //....
} catch(rational_exception const& ex) {
    switch(ex.code) {
        case kErrorAdditionOverflow: //....
        case kErrorMultiplicationOwerflow: //....
        //....
    }
} catch(std::exception const &ex) {
    /* TODO: */
} catch(...) {
    /* TODO */
}
Re: Наследование класса std::exception
От: Ops Россия  
Дата: 01.07.10 19:33
Оценка: 1 (1)
Здравствуйте, Mak_71_rus, Вы писали:

M__>Здравствуйте, форумчане!


M__>Подскажите пожалуёста, если я создаю собственный класс ошибок, всегда ли он должен быть производным от std::exception?


Никому он ничего не должен, можно вызвать ошибку любого класса, и обработать любую

M__>Я решил написать класс rational, представляющий смешанное число. В результате сложения может призойти переполнение, или может быть попытка присвоить знаменателю нулевое значение — всё это исключительные ситуации. Я создал простую иерархию классов ошибок, базовый класс содержит только номер ошибки, а все производные — функцию-член, возвращающие этот номер. Мне кажется, такая система удобна в отладке, но стоит ли её оставлять как есть? Может лучше наследовать базовый класс от std::exceptin? Просто все строки, возвращаемые функцией what занимают места намного больше, чем сам экземпляр класса.


Как правило, what не размножается, ибо это все-таки указатель, и если не извращаться (ога, это сложно в обработчике), то проблем не будет. Но вот в плане отладки номера ошибок — не самое удобное. Посмотрите boost::exception, вероятно одним велосипедом меньше станет.
Переубедить Вас, к сожалению, мне не удастся, поэтому сразу перейду к оскорблениям.
Re: Наследование класса std::exception
От: minorlogic Украина  
Дата: 01.07.10 19:47
Оценка:
Здравствуйте, Mak_71_rus, Вы писали:

M__>Просто все строки, возвращаемые функцией what занимают места намного больше, чем сам экземпляр класса.


Если это недостаток, уточните в чем ?
... << RSDN@Home 1.2.0 alpha 4 rev. 1237>>
Ищу работу, 3D, SLAM, computer graphics/vision.
Re: Наследование класса std::exception
От: Sni4ok  
Дата: 01.07.10 20:13
Оценка:
Здравствуйте, Mak_71_rus, Вы писали:

M__>Я решил написать класс rational, представляющий смешанное число.


а чем не устроили существующие варианты, например boost::rational ?
Re: Наследование класса std::exception
От: K13 http://akvis.com
Дата: 02.07.10 03:49
Оценка: 3 (2) +3 :)
M__> Может лучше наследовать базовый класс от std::exceptin? Просто все строки, возвращаемые функцией what занимают места намного больше, чем сам экземпляр класса.

лучше даже от std::runtime_error, наследника std::exception.

Сама идея экономить горстку байтиков в случае "шеф, усё пропало" (исключительной! ситуации) -- выглядит непонятной.
Re[3]: Наследование класса std::exception
От: pvirk Россия  
Дата: 02.07.10 05:01
Оценка:
Здравствуйте, kpcb, Вы писали:

K>Наследовать от std::exception не обязательно. Но если унаследовать — то ловить потом будет проще


K>а ловить его так

K>
K>try {
K>    //....
K>} catch(rational_exception const& ex) {
K>    switch(ex.code) {
K>        case kErrorAdditionOverflow: //....
K>        case kErrorMultiplicationOwerflow: //....
K>        //....
K>    }
K>} catch(std::exception const &ex) {
K>    /* TODO: */
K>} catch(...) {
K>    /* TODO */
K>}
K>


Я извиняюсь, а где здесь используется то, что было наследование? Что проще ловить стало?
Re: Наследование класса std::exception
От: MasterZiv СССР  
Дата: 02.07.10 06:46
Оценка: +3
Mak_71_rus wrote:
> Подскажите пожалуёста, если я создаю собственный класс ошибок, всегда ли
> он должен быть производным от std::exception?

Не должен. Не обязан. Но если ты его унаследуеш от стандартного std::exception
тебе и твоим коллегам будет легче жить. Просто потому что это стандартная
штука и одним catch можно обработать одинаково все исключения.

Не наследовать от std::exception имеет смысл только в каком-то старом
коде, расчитанном на компиляторы, живущие по старым стандартам.

> возвращающие этот номер. Мне кажется, такая система удобна в отладке, но

> стоит ли её оставлять как есть? Может лучше наследовать базовый класс от
> std::exceptin? Просто все строки, возвращаемые функцией what занимают

Конечно же только базовый.

> места намного больше, чем сам экземпляр класса.


what возвращает const char *

virtual const char *what( ) const;
Posted via RSDN NNTP Server 2.1 beta
Re[4]: Наследование класса std::exception
От: March_rabbit  
Дата: 02.07.10 06:57
Оценка:
Здравствуйте, pvirk, Вы писали:

P>Я извиняюсь, а где здесь используется то, что было наследование? Что проще ловить стало?

этот catch ловит и другие исключения, возникшие в коде. Что совсем неплохо
Re[2]: Наследование класса std::exception
От: Sni4ok  
Дата: 02.07.10 07:33
Оценка: -1
Здравствуйте, K13, Вы писали:

K13>лучше даже от std::runtime_error, наследника std::exception.


чем лучше, почему не от logic_error или не от domain_error ?
Re[4]: Наследование класса std::exception
От: kpcb Россия  
Дата: 02.07.10 08:27
Оценка:
Здравствуйте, pvirk, Вы писали:

P>Здравствуйте, kpcb, Вы писали:


K>>Наследовать от std::exception не обязательно. Но если унаследовать — то ловить потом будет проще


K>>а ловить его так

K>>
K>>try {
K>>    //....
K>>} catch(rational_exception const& ex) {
K>>    switch(ex.code) {
K>>        case kErrorAdditionOverflow: //....
K>>        case kErrorMultiplicationOwerflow: //....
K>>        //....
K>>    }
K>>} catch(std::exception const &ex) {
K>>    /* TODO: */
K>>} catch(...) {
K>>    /* TODO */
K>>}
K>>


P>Я извиняюсь, а где здесь используется то, что было наследование?

Наследование используется вот здесь:
catch(rational_exception const& ex)



P> Что проще ловить стало?

Своё собственное исключение. Если его не обрабатывать то на х оно нужно. Писать отдельный catch для кучи пораждённых классов — это маразм (ИМХО).
Re[3]: Наследование класса std::exception
От: Mak_71_rus Россия  
Дата: 02.07.10 13:47
Оценка: -1
K13>>лучше даже от std::runtime_error, наследника std::exception.

S>чем лучше, почему не от logic_error или не от domain_error ?


Ну это логично хотя бы потому, что все классы свидетельствуют именно об ошибках времени выполнения.
Re[4]: Наследование класса std::exception
От: Mak_71_rus Россия  
Дата: 02.07.10 13:52
Оценка:
Ну я делаю такой общий вывод:

— Классы исключений не обязаны наследовать стндартный класс std::exception (это понятно)
— Принято и считается хорошим тоном наследовать класс ошибок (прямо или через другие классы) от std::error
— Все мои классы ошибок описывают ошибки времени выполнения, поэтому их логично наследовать от std::runtime_error
Re[2]: Наследование класса std::exception
От: Mak_71_rus Россия  
Дата: 02.07.10 13:56
Оценка: +1
Здравствуйте, Sni4ok, Вы писали:

S>Здравствуйте, Mak_71_rus, Вы писали:


M__>>Я решил написать класс rational, представляющий смешанное число.


S>а чем не устроили существующие варианты, например boost::rational ?


Тем, что он уже написан, а я просто учюсь объектно-ориентированному программированию, нужно что-то самому написать, не очень сложное, зато как следует!
Re[4]: Наследование класса std::exception
От: Sni4ok  
Дата: 02.07.10 14:29
Оценка: +1
Здравствуйте, Mak_71_rus, Вы писали:

S>>чем лучше, почему не от logic_error или не от domain_error ?


M__>Ну это логично хотя бы потому, что все классы свидетельствуют именно об ошибках времени выполнения.


аха, а такой вот код, это ошибка выполнения- или таки не совсем?

rational<int> a(10,0);
Re[5]: Наследование класса std::exception
От: rg45 СССР  
Дата: 02.07.10 15:10
Оценка:
Здравствуйте, Sni4ok, Вы писали:

S>>>чем лучше, почему не от logic_error или не от domain_error ?


M__>>Ну это логично хотя бы потому, что все классы свидетельствуют именно об ошибках времени выполнения.


S>аха, а такой вот код, это ошибка выполнения- или таки не совсем?


S>
S>rational<int> a(10,0);
S>


А вот тут надо различать два разных момента: первый — это время, когда ошибка была допущена, второй — это когда она обнаруживается. В том месте, где ошибка обнаруживается, об истинных причинах ее возникновения как правило ничего не известно. И исключения как раз и являются средством реакции на ошибки в момент обнаружения. Ошибка, приведенная тобой в качестве примера, бесспорно, была допущена программистом на этапе кодирования, но обнаружится эта ошибка на этапе выполнения. Поэтому вполне естественно, что код, обнаруживший эту ошибку сообщит о ней исключением типа runtime_error или производным от него.
--
Справедливость выше закона. А человечность выше справедливости.
Re[6]: Наследование класса std::exception
От: Sni4ok  
Дата: 02.07.10 15:56
Оценка:
Здравствуйте, rg45, Вы писали:

R> Поэтому вполне естественно, что код, обнаруживший эту ошибку сообщит о ней исключением типа runtime_error или производным от него.



и почему не domain_error ?
Re[7]: Наследование класса std::exception
От: Sni4ok  
Дата: 02.07.10 16:51
Оценка:
Здравствуйте, Sni4ok, Вы писали:


S>и почему не domain_error ?


которая кстати является наследником logic_error, логическая ошибка- не значит что это ошибка в коде, просто ошибка логики выполнения программы.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.