Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.56/18: Рейтинг темы: голосов - 18, средняя оценка - 4.56
 Аватар для Nishen
1358 / 856 / 366
Регистрация: 26.02.2015
Сообщений: 3,814

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

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

Студворк — интернет-сервис помощи студентам
Добрый день!
Пишу класс дробей и, соответственно, если пользователь введёт 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
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
15.03.2017, 10:58
Ответы с готовыми решениями:

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

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

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

43
2549 / 1208 / 358
Регистрация: 30.11.2013
Сообщений: 3,826
15.03.2017, 15:05
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от hoggy Посмотреть сообщение
вкратце:
самому кидать исключение в конструкторе
и самому же в конструкторе его ловить - это какой то бред.
Ну даже памятник таком решению поставили в Батавия, штат Иллинойс
4
Форумчанин
Эксперт CЭксперт С++
 Аватар для MrGluck
8216 / 5047 / 1437
Регистрация: 29.11.2010
Сообщений: 13,453
15.03.2017, 15:10
Цитата Сообщение от rikimaru2013 Посмотреть сообщение
Ну даже памятник таком решению поставили в Батавия, штат Иллинойс
Тут правда скульптура сверху ещё нормально выглядит. В нашем случае же там было бы что-нибудь уродливое и непонятное.
2
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
15.03.2017, 15:45
Цитата Сообщение от 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
Я за вариант 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
Любитель чаепитий
 Аватар для GbaLog-
3745 / 1801 / 566
Регистрация: 24.08.2014
Сообщений: 6,020
Записей в блоге: 1
15.03.2017, 17:10
Цитата Сообщение от sys_beginner Посмотреть сообщение
чтоб аккуратно и без утечек
Ассерт ложит программу полностью.
Даже если и будут утечки, весь процесс прихлопнет ОС.
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
15.03.2017, 17:10
Цитата Сообщение от sys_beginner Посмотреть сообщение
Если нужно будет отлавливать проблемы
не нужно.
это класс дроби.
знаменатель в принципе не должен быть равен нулю.
если это не так, значит это программная ошибка.
(такая же, как например выход за пределы диапазона массива)

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

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

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

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

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

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

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

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

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

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

Добавлено через 42 секунды
И тогда бы не пришлось кидать исключения и использовать assert (даже в конструкторе).
0
2549 / 1208 / 358
Регистрация: 30.11.2013
Сообщений: 3,826
15.03.2017, 21:03
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
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
15.03.2017, 22:13
Цитата Сообщение от 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
Цитата Сообщение от hoggy Посмотреть сообщение
либо равны нулю.
Поспешил, писал тут в редакторе там оператор больше

Цитата Сообщение от hoggy Посмотреть сообщение
assert пишется с маленькой буквы.
а у меня с большой. И имею полное право))) тем более, что поведение Assert отличается от accert
0
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
16.03.2017, 10:16
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
Любитель чаепитий
 Аватар для GbaLog-
3745 / 1801 / 566
Регистрация: 24.08.2014
Сообщений: 6,020
Записей в блоге: 1
16.03.2017, 10:44
Цитата Сообщение от sys_beginner Посмотреть сообщение
не было создано объектов в динамической памяти
Прошу заметить, что тут речь идет только о сырых указателях, если есть умные указатели, то они сами память освободят, т.к. считаются автоматическими объектами.
1
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
16.03.2017, 12:04
GbaLog-,
Да ) Привет RAII
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
16.03.2017, 12:44
Цитата Сообщение от sys_beginner Посмотреть сообщение
Так что же я сказал не так?
вам нужно понять одну вещь.
assert именно для того и нужен,
что бы сообщить пользователю об ошибке.

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

вам и ТС нужно понять,
в чем различие "программной ошибки" и "нештатной систуации".
0
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
16.03.2017, 12:46
Цитата Сообщение от hoggy Посмотреть сообщение
assert именно для того и нужен,
что бы сообщить пользователю об ошибке.
И как пользователь библиотеки будет ловить эту ошибку и продолжать работать дальше?
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
16.03.2017, 13:00
Цитата Сообщение от sys_beginner Посмотреть сообщение
И как пользователь библиотеки будет ловить эту ошибку и продолжать работать дальше?
исправит ошибку у себя в коде.


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

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

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

Так вот, если разработчик конечной библиотеки будет использовать вашу версию с ассертом, то как конечный пользователь будет разбираться с ошибками? Лазить в исходный код либы а потом другой либы? Или как вообще будет оформлена документация такой библиотеки? "Вы знаете, мы в реализации нашей библиотеки используем другую библиотеку разработчик которой поставил там ассерт. Так что если программа упадет, это не по нашей вине! Следите за числами!" Так что ли? Казалось бы причем тут числа, ведь мы используем конечную библиотеку которая не является математической...
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
16.03.2017, 13:29
Помогаю со студенческими работами здесь

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

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

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

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

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


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

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами
8Observer8 20.02.2026
Содержание блога Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее. . .
Конвертировать закладки radiotray-ng в m3u-плейлист
damix 19.02.2026
Это можно сделать скриптом для PowerShell. Использование . \СonvertRadiotrayToM3U. ps1 <path_to_bookmarks. json> Рядом с файлом bookmarks. json появится файл bookmarks. m3u с результатом. # Check if. . .
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так: https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347 Основана на STM32F303RBT6. На борту пять. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru