1352 / 851 / 365
Регистрация: 26.02.2015
Сообщений: 3,799
1

Исключение в конструкторе шаблонного класса

15.03.2017, 10:58. Показов 3308. Ответов 43

Author24 — интернет-сервис помощи студентам
Добрый день!
Пишу класс дробей и, соответственно, если пользователь введёт 0 в знаменатель с помощью оператора >> или с помощью конструктора с 2мя параметрами, то нужно вызвать исключение. Но как это сделать, я не понимаю.

Fraction.h
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
template <class T>
class Fraction {
 
    public:
        Fraction();
        Fraction(T n, T d);
        ~Fraction();
 
        template <class T>
        friend const Fraction<T>& lowterms(Fraction<T>& fraction);
 
        //I/O operators
        template <class T>
        friend std::istream& operator >> (std::istream& stream, Fraction<T>& fraction);
        template <class T>
        friend std::ostream& operator << (std::ostream& stream, const Fraction<T>& fraction);
 
        //THROWS
        class denominatorEqualsToZero {};
 
    private:
        T numerator;
        T denominator;
 
};
 
template <class T>
Fraction<T>::Fraction(T n, T d) : numerator(n) {
 
    if (d == 0) {
 
        throw denominatorEqualsToZero();
 
    }  else {
 
        denominator = d;
 
    }
 
    lowterms(*this);
 
}


Сделал так, но при генерации исключения возникает ошибка "Возникло необработанное исключение по адресу ... исключение Microsoft C++: Fraction<int>::denominatorEqualsToZero ..."

Скажите, пожалуйста, как правильно выполнять исключения в конструкторах и, тем более, в шаблонных.
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
15.03.2017, 10:58
Ответы с готовыми решениями:

Инициализация шаблонного класса(В конструкторе класса после двоеточия вновь имя класса)
Всем доброго времени суток! Пытаюсь разобраться как работает приведенный мной код. Конкретно,...

Параметр const T & val = T() в конструкторе шаблонного класса
Добрый день! Начал разбираться с шаблонами и наткнулся на такой пример: template &lt; typename T...

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

Исключение в конструкторе класса
Всем здравствуйте! Что будет с классом, если в его конструкторе вылетело и не перехватилось...

43
2549 / 1208 / 358
Регистрация: 30.11.2013
Сообщений: 3,826
15.03.2017, 15:05 21
Author24 — интернет-сервис помощи студентам
Цитата Сообщение от hoggy Посмотреть сообщение
вкратце:
самому кидать исключение в конструкторе
и самому же в конструкторе его ловить - это какой то бред.
Ну даже памятник таком решению поставили в Батавия, штат Иллинойс
Исключение в конструкторе шаблонного класса
4
Форумчанин
Эксперт CЭксперт С++
8215 / 5045 / 1437
Регистрация: 29.11.2010
Сообщений: 13,453
15.03.2017, 15:10 22
Цитата Сообщение от rikimaru2013 Посмотреть сообщение
Ну даже памятник таком решению поставили в Батавия, штат Иллинойс
Тут правда скульптура сверху ещё нормально выглядит. В нашем случае же там было бы что-нибудь уродливое и непонятное.
2
872 / 459 / 90
Регистрация: 10.06.2014
Сообщений: 2,665
15.03.2017, 15:45 23
Цитата Сообщение от hoggy Посмотреть сообщение
assert(d != 0 && "Denominator cannot be equals to zero!");
Если нужно будет отлавливать проблемы когда d == 0 и продолжать работать дальше, такой вариант не подойдет
В случае библиотечного кода вариант ТС с эксепшеном в конструкторе нормальный
Главное чтоб аккуратно и без утечек
0
2549 / 1208 / 358
Регистрация: 30.11.2013
Сообщений: 3,826
15.03.2017, 15:53 24
Я за вариант hoggy , с assert - уже вижу код sys_beginner,
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    void fn( int a, int b)
    {
        Drob* ptr = nullptr;
        try
        {
            ptr = new Drob( a, b );
        }       
        catch (ZeroExeption& e)
        {
            ptr = new Drob( a, 1 );
        }
 
        ptr->doStuff();
 
    }
и понимаю, что кто-то не понимает разницы между exeption и assert
0
Любитель чаепитий
3742 / 1798 / 566
Регистрация: 24.08.2014
Сообщений: 6,016
Записей в блоге: 1
15.03.2017, 17:10 25
Цитата Сообщение от sys_beginner Посмотреть сообщение
чтоб аккуратно и без утечек
Ассерт ложит программу полностью.
Даже если и будут утечки, весь процесс прихлопнет ОС.
0
Эксперт С++
8739 / 4317 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
15.03.2017, 17:10 26
Цитата Сообщение от sys_beginner Посмотреть сообщение
Если нужно будет отлавливать проблемы
не нужно.
это класс дроби.
знаменатель в принципе не должен быть равен нулю.
если это не так, значит это программная ошибка.
(такая же, как например выход за пределы диапазона массива)

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

таким образом ассерт защиты вполне достаточно для данного случая.

кроме того, не забываем:
эксепшены не бесплатны.
они просаживают рантайм,
и не позволяют компиляторам сгенерировать максимально эффективный код.

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

поэтому, конструктор класса дробей должен быть помечен
как "никогда не кидающий исключения",
что позволит компилятору сгенерировать более эффективный код.
3
872 / 459 / 90
Регистрация: 10.06.2014
Сообщений: 2,665
15.03.2017, 17:58 27
rikimaru2013,
Откуда вы видите? Вы бы сначала попросили привести пример а потом уже делали бы выводы
Моя мысль никак не связана с реализацией которую вы описали

Цитата Сообщение от GbaLog- Посмотреть сообщение
Ассерт ложит программу полностью.
Даже если и будут утечки, весь процесс прихлопнет ОС.
Понимаю Но я не об этом

Цитата Сообщение от hoggy Посмотреть сообщение
это класс дроби.
знаменатель в принципе не должен быть равен нулю.
Я имел ввиду в общем случае
Зависит от логики
Например может быть так что эта цифра получается из вне от пользователя
И когда он передает 0 нужно просто показать красивую ошибку а не укладывать программу спать
0
Эксперт С++
8739 / 4317 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
15.03.2017, 18:48 28
Цитата Сообщение от sys_beginner Посмотреть сообщение
Я имел ввиду в общем случае
нет никаких "общих случаев".

на ноль делить нельзя вне зависимости от ситуации

Цитата Сообщение от sys_beginner Посмотреть сообщение
Зависит от логики
не существует логики, в рамках которой допустимо делить на ноль.

Цитата Сообщение от sys_beginner Посмотреть сообщение
Например может быть так что эта цифра получается из вне от пользователя
тут вроде по-русски написано, не?
Цитата Сообщение от hoggy Посмотреть сообщение
в тех случаях, когда данные приходят откуда то извне,
валидировать их нужно сразу при поступлении.
то бишь перед тем, как кормить внутреннию инфраструктуру .
0
2549 / 1208 / 358
Регистрация: 30.11.2013
Сообщений: 3,826
15.03.2017, 18:57 29
Цитата Сообщение от sys_beginner Посмотреть сообщение
Откуда вы видите?
Опыт) Но если вам не сложно - покажите как вы видите применение exeption в дробях
0
1352 / 851 / 365
Регистрация: 26.02.2015
Сообщений: 3,799
15.03.2017, 20:55  [ТС] 30
Т.е. если бы я сейчас писал программу с красивым финтифлюшным интерфейсом, то чтобы не закрывать программу с помощью assert, мне нужно было бы проверить введенные пользователем данные ДО вызова конструктора класса Fraction, выдать красивое окно с ошибкой и предложить ввести данные повторно?

Добавлено через 42 секунды
И тогда бы не пришлось кидать исключения и использовать assert (даже в конструкторе).
0
2549 / 1208 / 358
Регистрация: 30.11.2013
Сообщений: 3,826
15.03.2017, 21:03 31
Nishen, вот пример assert

C++
1
2
3
4
5
6
void Windows::resize( const size_t w, const size_t h )
{
    Assert( w >= 0u );
    Assert( h >= 0u );
    SetWindowSize( w, h );
}
0
Эксперт С++
8739 / 4317 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
15.03.2017, 22:13 32
Цитата Сообщение от Nishen Посмотреть сообщение
И тогда бы не пришлось кидать исключения и использовать assert (даже в конструкторе).
1.
assert - отладочное средство.
его код не попадает в релизную сборку.

2.
программисты - люди.
иногда они ошибаются.
assert`тами проверяются несбыточные ситуации,
которых не должно быть в принципе.
на этапе разработки это даёт дополнительную защиту
от ошибок.

Добавлено через 1 минуту
Цитата Сообщение от rikimaru2013 Посмотреть сообщение
вот пример assert
Цитата Сообщение от rikimaru2013 Посмотреть сообщение
size_t w
Цитата Сообщение от rikimaru2013 Посмотреть сообщение
Assert( w >= 0u );
1.
assert пишется с маленькой буквы.

2.
тип данных w - беззнаковое.
0u - тоже беззнаковое.
итого:
проверка абсолютно бессмысленная.
потому что беззнаковые всегда больше либо равны нулю.
0
2549 / 1208 / 358
Регистрация: 30.11.2013
Сообщений: 3,826
15.03.2017, 22:56 33
Цитата Сообщение от hoggy Посмотреть сообщение
либо равны нулю.
Поспешил, писал тут в редакторе там оператор больше

Цитата Сообщение от hoggy Посмотреть сообщение
assert пишется с маленькой буквы.
а у меня с большой. И имею полное право))) тем более, что поведение Assert отличается от accert
0
872 / 459 / 90
Регистрация: 10.06.2014
Сообщений: 2,665
16.03.2017, 10:16 34
rikimaru2013,
Я имел ввиду, что если переданное число равно нулю - просто бросить исключение. При этом убедиться что перед броском не было создано объектов в динамической памяти
C++
1
2
3
4
5
6
7
8
struct Foo
{
    Foo(int num)
    {
        if (num == 0) throw 123;
        //do something
    }
};
Теперь о том, почему я поддержал этот подход. Отвечу на пост hoggy
Цитата Сообщение от hoggy Посмотреть сообщение
нет никаких "общих случаев".
на ноль делить нельзя вне зависимости от ситуации
Зачем вы пристали к этому нулю? Под общим случаем имеется ввиду "броски исключения в конструкторах", и хочу заметить, что такие случаи все таки есть. Например, std::regex.
Цитата Сообщение от hoggy Посмотреть сообщение
в тех случаях, когда данные приходят откуда то извне,
валидировать их нужно сразу при поступлении.
то бишь перед тем, как кормить внутреннию инфраструктуру .
Я с этим согласен, об этом свидетельствует мой пост, где я предложил такой же расклад
Исключение в конструкторе шаблонного класса
Но чуть позже ТС сказал, как быть, если он пишет библиотечный код и нужно иметь возможность сообщать пользователям библиотеки тогда, когда библиотека используется некорректно. Вот тот самый пост:
Исключение в конструкторе шаблонного класса
После этого я поддержал идею с исключениями, думаю уже стало понятно почему
Далее вы предложили вариант с assert тут
Исключение в конструкторе шаблонного класса
Я в свою очередь не согласился ввиду того, что assert завалит программу и пользователю библиотеки мы уже ничего в случае ошибки сообщить не сможем.

Так что же я сказал не так?

Добавлено через 9 минут
P.S Мы же не нолики и единички обсуждаем, а конечный результат который нужен ТС
0
Любитель чаепитий
3742 / 1798 / 566
Регистрация: 24.08.2014
Сообщений: 6,016
Записей в блоге: 1
16.03.2017, 10:44 35
Цитата Сообщение от sys_beginner Посмотреть сообщение
не было создано объектов в динамической памяти
Прошу заметить, что тут речь идет только о сырых указателях, если есть умные указатели, то они сами память освободят, т.к. считаются автоматическими объектами.
1
872 / 459 / 90
Регистрация: 10.06.2014
Сообщений: 2,665
16.03.2017, 12:04 36
GbaLog-,
Да ) Привет RAII
0
Эксперт С++
8739 / 4317 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
16.03.2017, 12:44 37
Цитата Сообщение от sys_beginner Посмотреть сообщение
Так что же я сказал не так?
вам нужно понять одну вещь.
assert именно для того и нужен,
что бы сообщить пользователю об ошибке.

Цитата Сообщение от sys_beginner Посмотреть сообщение
P.S Мы же не нолики и единички обсуждаем, а конечный результат который нужен ТС
именно нолики в данным случае.

вам и ТС нужно понять,
в чем различие "программной ошибки" и "нештатной систуации".
0
872 / 459 / 90
Регистрация: 10.06.2014
Сообщений: 2,665
16.03.2017, 12:46 38
Цитата Сообщение от hoggy Посмотреть сообщение
assert именно для того и нужен,
что бы сообщить пользователю об ошибке.
И как пользователь библиотеки будет ловить эту ошибку и продолжать работать дальше?
0
Эксперт С++
8739 / 4317 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
16.03.2017, 13:00 39
Цитата Сообщение от sys_beginner Посмотреть сообщение
И как пользователь библиотеки будет ловить эту ошибку и продолжать работать дальше?
исправит ошибку у себя в коде.


Цитата Сообщение от hoggy Посмотреть сообщение
вам и ТС нужно понять,
в чем различие "программной ошибки" и "нештатной систуации".
0
872 / 459 / 90
Регистрация: 10.06.2014
Сообщений: 2,665
16.03.2017, 13:29 40
hoggy,
Не хочу спорить но тем не менее

С точки зрения пользователя это может не считаться ошибкой
Получаются данные откуда угодно - и передаются в конструктор объекта
Вариант с ассертом тут не подходит

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

Так вот, если разработчик конечной библиотеки будет использовать вашу версию с ассертом, то как конечный пользователь будет разбираться с ошибками? Лазить в исходный код либы а потом другой либы? Или как вообще будет оформлена документация такой библиотеки? "Вы знаете, мы в реализации нашей библиотеки используем другую библиотеку разработчик которой поставил там ассерт. Так что если программа упадет, это не по нашей вине! Следите за числами!" Так что ли? Казалось бы причем тут числа, ведь мы используем конечную библиотеку которая не является математической...
0
16.03.2017, 13:29
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
16.03.2017, 13:29
Помогаю со студенческими работами здесь

Как корректно передать в метод шаблонного класса объект шаблонного класса в качестве параметра?
header.h template &lt;class T&gt; class MyVector { public: void swap(MyVector&lt;T&gt;Vector); }...

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

В конструкторе копирования отцовского (_str) класса возникает некое "необработанное исключение"
Добрый день. Делаю курсовик в универе, иерархия классов и работа с ними. В конструкторе...

Возможно ли создание объекта шаблонного класса в функции этого класса?
Доброго времени суток, уважаемые форумчане :) Мне по лабам задали задание - реализовать шаблон...

Чем отличается шаблонный метод класса от шаблонного класса?
Чем отличается шаблонный метод класса от шаблонного класса???????ПЛИЗ!!!!Если можно немного ссылок...

Исключение в конструкторе
#include &lt;iostream&gt; class Vect { public: Vect(char); ~Vect() { try { delete p; }...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru