![]() |
Модераторы: Daevaorn |
![]() ![]() ![]() |
|
itan |
|
||||||
Новичок Профиль Группа: Участник Сообщений: 8 Регистрация: 3.7.2006 Репутация: нет Всего: нет |
Вот есть у меня свой тип данных :
и есть функция, которая принимает этот тип в качестве параметра:
Вопрос в том - как мне можно защитить функцию func от передачи ей значений не свойственных типу Type , например таким образом:
Для усложнения задачи предположим, что количество "типов" у Type может быть большим и разброс их значений существеннен. |
||||||
|
|||||||
Anikmar |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2513 Регистрация: 26.11.2006 Где: Санкт-Петербург Репутация: 9 Всего: 59 |
Она уже защищена.
При попытке вызвать функцию с параметром int будет выдано предупреждение компилятора (или ошибка, не помню точно) о несовпадении параметров или о неявном преобразовании т.е. чтобы компилилось без проблем нельзя будет писать func(0); Надо будет писать func(Type1) |
|||
|
||||
JackYF |
|
|||
![]() полуавантюрист ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 5814 Регистрация: 28.8.2004 Где: страна тысячи озё р Репутация: 18 Всего: 162 |
Именно, что предупреждение. Тут этого ИМХО недостаточно. Программист при желании сможет передать в функцию любое целое число. Так что фильтровать, так или иначе, придется. |
|||
|
||||
Anikmar |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2513 Регистрация: 26.11.2006 Где: Санкт-Петербург Репутация: 9 Всего: 59 |
Си чем и хорош - тут программист может творить практически все что угодно - на то он и программист, чтобы следить за собой.
А в данном случае - я не уверен, что компилятор схавает значение, выходящее за пределы нумератора, хотя и не пробовал, не знаю... Чтобы полностью защищать функции - лучше работать на паскале. В Си с помощью преобразования типов - такого можно наворотить... Никакими защитами не избежать. Вообще-то я слышал о дуракоустойчивости программ по отношению к пользователям, а вот чтобы она дуракоустойчивая по отношению к программистам была... В конце концов одну проверку в функцию поставить не так уж и сложно. |
|||
|
||||
Fazil6 |
|
|||
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1653 Регистрация: 3.5.2006 Где: Минск Репутация: 35 Всего: 60 |
ерунда. Лучше - это вообще ничего не делать. А вообще int автоматом не приводится к enum, а если вы взламывать будете static_cast-ом или reinterpret , то что же вы хотели? Не лгите компиллятору , иначе он будет мстить. Это сообщение отредактировал(а) Fazil6 - 12.12.2006, 14:51 |
|||
|
||||
Anikmar |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2513 Регистрация: 26.11.2006 Где: Санкт-Петербург Репутация: 9 Всего: 59 |
Целиком и полностью с этим согласен. |
|||
|
||||
UnrealMan |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 722 Регистрация: 30.3.2006 Репутация: 27 Всего: 32 |
||||
|
||||
JackYF |
|
|||
![]() полуавантюрист ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 5814 Регистрация: 28.8.2004 Где: страна тысячи озё р Репутация: 18 Всего: 162 |
||||
|
||||
UnrealMan |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 722 Регистрация: 30.3.2006 Репутация: 27 Всего: 32 |
Явное разрешено:
|
|||
|
||||
Anikmar |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2513 Регистрация: 26.11.2006 Где: Санкт-Петербург Репутация: 9 Всего: 59 |
C++ Builder никаких проверок не делает. Выдает предупреждение: инициализация нумератора целым числом.
Вывод: C++ Builder НЕНОРМАЛЬНЫЙ компилятор! ![]() Но если серьезно, нормальный программер на Си должен обязательно поглядывать на предупреждения, за некоторыми из них - 100% ошибка, например "Возможно некорректное присваивание" - по запаре забыл второе равно воткнуть в условие и т.п. Так что все равно смотреть надо, что пишешь. Если программер сам ручками пишет некое преобразование (MyEnumType)99999 - то ему и флаг в руки! |
|||
|
||||
maxim1000 |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 3334 Регистрация: 11.1.2003 Где: Киев Репутация: 17 Всего: 110 |
где-то встречал такой подход:
вместо enum делается класс конструкторы прячутся (только копирования оставляют) зато делают несколько функций типа
и пользуются в программе значениями January(), February(), ... а static_cast in в класс, по-моему, даёт ошибку... -------------------- qqq |
|||
|
||||
JackYF |
|
|||
![]() полуавантюрист ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 5814 Регистрация: 28.8.2004 Где: страна тысячи озё р Репутация: 18 Всего: 162 |
Программер, пишущий код, должен максимально защитить свой код от неправильных входных параметров.
Объявлять, что параметр должен передаваться только так и никак иначе - это не выход. Гораздо безопаснее все-таки внутри функции отсеивать неправильные значения.
Писать код желательно с расчетом на то, что результирующий программист будет делать с приведенным интерфейсом что угодно. ИМХО пиши проверки. Хотя бы в дебаг-версии..., или с какой-нибудь другой условной компиляцией... |
|||
|
||||
UnrealMan |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 722 Регистрация: 30.3.2006 Репутация: 27 Всего: 32 |
Именно так! Всё, что не разрешено стандартом, запрещено. Разработчик компилятора не вправе пороть отсебятину, в частности – расширять множество неявных преобразований, перечисленных в стандарте C++ (а возможность неявного преобразования целого в перечисление там нигде не указана). Например, если мы сделаем перегрузку:
при вызове Func(1) по стандарту обязана вызваться функция с эллипсисом. А ежели в программе, сгенеренной компилятором, вызывается вторая функция (и компилятор ещё смеет сыпать тут своими дурацкими предупреждениями – мол, посмотрите, какие умные вам разработчики компилятора попались: авторы стандарта им в подмётки не годятся), то место такому компилятору в топке. |
|||
|
||||
JackYF |
|
|||
![]() полуавантюрист ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 5814 Регистрация: 28.8.2004 Где: страна тысячи озё р Репутация: 18 Всего: 162 |
Так-то оно так, но: 1) как минимум разработчики компиляторов GCC, MSVC, BCC порят отсебятину (каждый свою). 2) во всех этих компиляторах возможно включение опции типа "Ansi компиляция", которая отменяет все эти самые навороты и перевороты. |
|||
|
||||
Anikmar |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2513 Регистрация: 26.11.2006 Где: Санкт-Петербург Репутация: 9 Всего: 59 |
На счет приведенного примера перегрузки (оставляю свое мнение на подобный код при себе) - мне стало интересно. В Билдере срабатывает функция (...)
Хотя я ожидал, что комп запутается. |
|||
|
||||
JackYF |
|
|||
![]() полуавантюрист ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 5814 Регистрация: 28.8.2004 Где: страна тысячи озё р Репутация: 18 Всего: 162 |
Как именно ты еще при этом вызываешь? С явным преобразованием или без? |
|||
|
||||
Anikmar |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2513 Регистрация: 26.11.2006 Где: Санкт-Петербург Репутация: 9 Всего: 59 |
Вызываю Func(1) - без явного, как и требовалось в примере
|
|||
|
||||
JackYF |
|
|||
![]() полуавантюрист ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 5814 Регистрация: 28.8.2004 Где: страна тысячи озё р Репутация: 18 Всего: 162 |
Anikmar, тогда можно локально поздравить Билдер
![]() |
|||
|
||||
UnrealMan |
|
||||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 722 Регистрация: 30.3.2006 Репутация: 27 Всего: 32 |
Насчёт gcc я хотел бы посмотреть примерчики (мне пока только пару багов удалось обнаружить, не считая отсутствия поддержки экспорта шаблонов :-) ). В метапрограммировании подобный код используется в порядке вещей :-) А, ну тогда предупреждение в случае без перегрузки в общем-то сойдёт :-) Кстати, чего Builder (какой он у тебя версии?) выведет вот тут?
Это сообщение отредактировал(а) UnrealMan - 12.12.2006, 19:17 |
||||
|
|||||
JackYF |
|
|||
![]() полуавантюрист ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 5814 Регистрация: 28.8.2004 Где: страна тысячи озё р Репутация: 18 Всего: 162 |
Как тебе строчки:
|
|||
|
||||
Anikmar |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2513 Регистрация: 26.11.2006 Где: Санкт-Петербург Репутация: 9 Всего: 59 |
На предложенный код, мой Билдер (6 версия) показал следующее:
enum En { en_zero = 0, en_two = 2 }; const int i_zero = en_zero; void Func1(...) { cout<<"Func1(...)"<<endl; } void Func1(bool) { cout<<"Func1(bool)"<<endl; } void Func2(...) { cout<<"Func2(...)"<<endl; } void Func2(int *) { cout<<"Func2(int *)"<<endl; } int main() { En en = en_two; Func1(en); // Вызывается (bool) Func2(en_zero); // Вызывается (int*) Func2(en_zero*1); // Вызывается (...) Func2(en_zero*0); // Вызывается (...) Func2(i_zero); // Вызывается (...) } Касаемо стандартов и нарушений стандартов - лично я считаю, что явного нарушения стандарта в том, что неявное преобразование целого к нумератору не вызывает именно ошибки, а только предупреждение - оправдано. Думаю это связано с архитектурой визуального программирования - очень много свойств хранится в виде int, а грузится в свойства типа "нумератор" - если бы там были ошибки, то сложно было расширять систему (лично мое мнение). А по поводу расширения стандарта - никакой боле-менее серьезный (а особенно красивый) проект не будет компилироваться в разных средах просто так - все равно поработать с ним придется. Если человек пишет достаточно большую систему на VC ну никак он ее не перенесет на Builder просто так на уровне исходников. Либо он не должен пользоваться практически никакими прелестями VC На чистом стандарте можно писать небольшие модули с узкоспециализированными задачами (например, сложную математику). Как только лезешь в украшательства проекта (а это сейчас не последнее место заниемает в программерстве) то волей неволей начинаешь пользоваться расширениями стандарта, которые имеются у конкретного компилятора. Не берусь судить - нормально это или нет, но принять как данность придется... |
|||
|
||||
UnrealMan |
|
||||||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 722 Регистрация: 30.3.2006 Репутация: 27 Всего: 32 |
Главное, чтоб корректно написанная на чистом C++ программа работала так, как предписывает ей работать стандарт. Если это не выполняется, то компилятор однозначно плох (насколько – зависит от характера и количества расхождений). Ну а расширения, делающие из некорректно составленной (с т.з. чистого C++) программы корректную (для данного компилятора) – эт, в принципе, вещь допустимая. Хотя я сомневаюсь, что вот такая некорректно составленная программа
в MinGW работает благодаря какому-то целенаправленно созданному расширению, учитывая что следующая программа
уже не компилируется :-) А, ну да, чего-то такое припоминаю :-) У такого объекта ещё тип какой-то странный, и для него typeid неприменим. Ты точно ничего не перепутал? :-)) Должно быть:
|
||||||
|
|||||||
Anikmar |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2513 Регистрация: 26.11.2006 Где: Санкт-Петербург Репутация: 9 Всего: 59 |
Нет, ничего не перепутал - у меня выдало так
|
|||
|
||||
UnrealMan |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 722 Регистрация: 30.3.2006 Репутация: 27 Всего: 32 |
||||
|
||||
![]() ![]() ![]() |
Правила форума "С++:Общие вопросы" | |
|
Добро пожаловать!
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn |
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |