0 / 0 / 0
Регистрация: 09.10.2018
Сообщений: 87
|
||||||||||||||||
1 | ||||||||||||||||
Условия для конструктора с параметрами22.04.2021, 02:35. Показов 4771. Ответов 17
Метки нет (Все метки)
Здравствуйте. Я определила конструктор объекта Group в файле .cpp:
Но я указала условие при заполнении массива данными. Можно ли добавить какое-то услове в сам конструктор? Еще преподавательпишет, что нет проверки в функции добавления элементов в группу, можно передать любой номер. Если я добавлю условие через assert, это будет корректоно?
0
|
22.04.2021, 02:35 | |
Ответы с готовыми решениями:
17
Наследование конструктора с параметрами Из конструктора без параметров в конструктор с параметрами Ошибка при вызове конструктора с параметрами Вызов базового конструктора с параметрами из дочернего класса |
Мозгоправ
|
|||||||||||
22.04.2021, 03:27 | 2 | ||||||||||
Ann1984, Group - это аналог std::vector?
Нужно. В конструкторе параметр размера и, соответственно, член класса size, можно сделать типа size_t, который беззнаковый. Тем более, что вы его применяете в операторе new[], который принимает как раз size_t. Либо, если уж так необходимо именно int, можно на невалидный параметр либо выбрасывать исключение (до выделения памяти), либо, при отрицательном параметре, обнулять член size. Тогда, с учётом контроля индекса при обращении к экземпляру класса (см. ниже), с этим экземпляром не получится ничего сделать. Да, будут ошибочные ситуации, которые в любом случае придётся обрабатывать, но программа не будет крашиться или выдавать бессмысленные результаты. Правильно пишет. Надо добавить проверку. Нет. assert() работает только для конфигурации Debug. В релизной конфигурации этот вызов будет выпилен. Надо добавлять нормальную проверку значения индекса на выход за пределы массива. Тут возникает вопрос: а что делать, если индекс не прошёл проверку? Вариантов несколько: 1. Сделать вид, что ничего не произошло. Т.е. просто выйти из метода. Категорически не рекомендуется. 2. Выдать диагностическое сообщение в cerr и выйти из метода. Тоже не рекомендуется. Можно использовать на этапе отладки, но не далее. Да и не всегда cerr доступен. 3. Вернуть из метода признак ошибки. Например:
4. Выкинуть исключение. При этом надо решить какого вида будет исключение. Обычно используются либо стандартные классы исключений из <stdexcept>, либо класс exception из <exception>, либо свой класс исключения, унаследованный от exception, либо чисто свой класс исключения. Например:
2
|
0 / 0 / 0
Регистрация: 09.10.2018
Сообщений: 87
|
|||||||||||
22.04.2021, 04:10 [ТС] | 3 | ||||||||||
L0M , спасибо за подсказки. Если я в конструкторе пропишу тип size_t , то это поможет избежать отриц.значений. Но как исключить нулевые? Ведь просто так прописывать нельзя?
Еще преподаватель указал, что в перегруженный оператор [ ] можно передать некорректный индекс, и это не проверяется. Я добавила проверку через assert, гугл подсказал. Но получается что его нельзя так использовать. Или тут это допустимо?
0
|
Мозгоправ
|
|
22.04.2021, 04:54 | 4 |
Не нужно исключать нулевое значение. Я вам в предыдущем сообщении написал
new Ship[0] - вполне законная конструкция. И в деструкторе такой блок памяти нулевого размера нужно освобождать также, как и обычный. Строка 4 в первом фрагменте бессмысленна. С operator [] ситуация аналогична методу PutShip() с тем отличием, что вернуть признак ошибки невозможно. Т.е. вариант 3 исключается. Наилучшее решение - бросить исключение.Для std::vector::operator[] в случае невалидного индекса написано, что результат неопределён. Т.е. классический случай UB. В реальности в std::vector::operator[] компилятор Visual Studio 2019 16.9.4 тупо не проверяет индекс на выход за границу массива (в отличие от метода std::vector::at(), который в случае невалидного индекса выбрасывает исключение). При этом в лучшем случае портится куча, а в худшем будет обращение к памяти, не принадлежащей куче. В обоих случаях прилетит исключение, но только уже от системы, вопрос только в том, когда это произойдёт (и как долго придётся потом искать где ошибка). Подсказками Гугла надо с умом пользоваться Ещё раз: assert() только для отладочной конфигурации. Этот макрос предназначен для отладки. В релизной конфигурации он не работает.
1
|
0 / 0 / 0
Регистрация: 09.10.2018
Сообщений: 87
|
||||||
23.04.2021, 12:55 [ТС] | 5 | |||||
L0M, я тут попробовала написать обработчик исключений. Похоже на правду?
0
|
18901 / 9859 / 2410
Регистрация: 30.01.2014
Сообщений: 17,302
|
|
23.04.2021, 16:58 | 7 |
Тут по условию задачи, честно говоря ,не понятно однозначно, что такой вариант не подходит.
Конечно можно. Тут все зависит от того, что именно вы вкладываете в понятие "некорректный индекс". Если некорректный индекс - это логическое состояние вашей программы, то да, нужно исключение. Если некорректный индекс в вашей программе невозможен в принципе, то нужен ассерт. Для примера с std::vector реализованы сразу обе стратегии: 1) Отладочная версия operator[] бросается ассертами, потому что operator[] предполагается к использования в контекстах, где некорректный индекс невозможен в принципе, например в пределах цикла, который ограничивает индексацию своим условием в корректных пределах. Ассерт определяет инвариант, который мы проверяем при разработке, а когда программа отлажена, со спокойной совестью выкидываем проверку, чтобы не тратить на нее время: мы же уже удостоверились на этапе отладки\тестирования что у нас нигде в программе не допускаются некорректные состояния. 2) Функция at() бросается исключением, потому что она предполагается к использования в случаях, когда неправильный индекс является частью логики вашей программы. Например, если его вводит пользователь (он может ошибиться) или он читается из файла (файл может быть неправильным). Тут стоит отметить, что второй случай всегда можно реализовать с помощью первого, просто перенеся проверку логического состояния на уровень выше, таким образом, чтобы исключить срабатывание ассерта, но это уже второй вопрос.
1
|
Мозгоправ
|
|
23.04.2021, 17:07 | 8 |
ТС написала, что "преподаватель указал, что в перегруженный оператор [ ] можно передать некорректный индекс". Видимо всё-таки предполагается, что в релизе некорректный индекс может быть. Поэтому я предложил кидать исключение.
А вот не бросается. По крайней мере в Visual Studio 2019 16.9.4. Специально проверял, перед тем как написать об этом в #4.
1
|
18901 / 9859 / 2410
Регистрация: 30.01.2014
Сообщений: 17,302
|
|
23.04.2021, 18:19 | 9 |
Бросается.
Это настраивается. Не помню точно как это сделать из интерфейса студии, но в конечном счете должен быть определен макрос _ITERATOR_DEBUG_LEVEL=1 Добавлено через 3 минуты И все-таки на всякий случай лучше не быть столь категоричным. А то у ТС может сложиться неверное понимание общей картины.
1
|
0 / 0 / 0
Регистрация: 09.10.2018
Сообщений: 87
|
|||||||||||
24.04.2021, 07:05 [ТС] | 10 | ||||||||||
L0M,
у меня есть файл group.cpp. Там описана данная функция:
Есть файл main.cpp, где она вызывается
0
|
18901 / 9859 / 2410
Регистрация: 30.01.2014
Сообщений: 17,302
|
|||||||||||
24.04.2021, 17:58 | 11 | ||||||||||
Убрать из функции:
1
|
0 / 0 / 0
Регистрация: 09.10.2018
Сообщений: 87
|
||||||||||||||||
06.05.2021, 07:27 [ТС] | 12 | |||||||||||||||
Я попробовала изменить код, опираясь на Ваши комментарии.
Вот что вышло. group.cpp ...
...
Но работа не прошла, так преподаватель написала: "В перегруженный оператор [] можно передать некорректный индекс, и это не проверяется. Сейчас исправлено всё ещё не полностью. Отрицательные значения?" Вот хочу спросить тут, а разве тип "size_t " не исключает отрицательные элементы?
0
|
6579 / 4564 / 1843
Регистрация: 07.05.2019
Сообщений: 13,726
|
|
06.05.2021, 08:42 | 13 |
Исключает. Проверки if (i >= size) достаточно. Только size тоже должен иметь тип size_t
1
|
DrOffset
|
06.05.2021, 13:14
#14
|
0
|
0 / 0 / 0
Регистрация: 09.10.2018
Сообщений: 87
|
|||||||||||||||||||||
06.05.2021, 15:42 [ТС] | 15 | ||||||||||||||||||||
Спасибо всем, вроде все учла .
Еще такой вопрос. Преподаватель пишет: "В конструктор с параметрами для группы допускается сейчас передавать отрицательное или нулевое количество элементов. Аналогично далее нет проверки в функции добавления элементов в группу, можно передать любой номер. Исправлено не полностью." Вот мой конструктор с параметрами: group.cpp ...
group.cpp ...
В main.cpp пишу:
Подскажите пожалуйста, что я не учла или неправильно указала. p.s. в group.h исправила тип:
0
|
18901 / 9859 / 2410
Регистрация: 30.01.2014
Сообщений: 17,302
|
||||||
06.05.2021, 22:42 | 16 | |||||
Ann1984, все у вас правильно.
Добавлено через 7 минут Это допустимо. В случае нуля конструкция
Разыменовывать такой указатель нельзя, но у вас от этого защищают проверки в методах PutShip и operator[] .
0
|
51 / 149 / 33
Регистрация: 29.06.2019
Сообщений: 1,428
|
|
09.05.2021, 09:07 | 17 |
? правильно ли будет моё предположение, что в функциях классов (помимо того, что в Ctor и Dtor само собой разумеющееся) тоже вообще лучше не выбрасывать исключения?.. а всё отлавливать только на стороне клиента (пользователя объектом класса)...
0
|
18901 / 9859 / 2410
Регистрация: 30.01.2014
Сообщений: 17,302
|
|
09.05.2021, 09:54 | 18 |
Это все зависит от выбранного подхода к построению архитектуры. В общем говоря, можно и так и так делать.
1
|
09.05.2021, 09:54 | |
09.05.2021, 09:54 | |
Помогаю со студенческими работами здесь
18
Как определить наличие конструктора с заданными параметрами? Вызывается конструктор по умолчанию вместо конструктора с параметрами Вызов конструктора с несколькими параметрами при использовании push_back() в vector'е Программа стала работать некорректно при добавлении конструктора с параметрами Класс Time, конструкторы с параметрами "содержит более одного конструктора по умолчанию" Почему при вызове конструктора из конструктора нельзя передавать this как аргумент? Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |