Стандарты программирования на С++. 101 правило и рекомендация
Шрифт:
40. Избегайте возможностей неявного преобразования типов
Не все изменения прогрессивны: неявные преобразования зачастую приносят больше вреда, чем пользы. Дважды подумайте перед тем, как предоставить возможность неявного преобразования к типу и из типа, который вы определяете, и предпочитайте полагаться на явные преобразования (используйте конструкторы, объявленные как
Неявные преобразования типов имеют две основные проблемы.
• Они могут проявиться в самых неожиданных местах.
• Они не
Неявно преобразующие конструкторы (конструкторы, которые могут быть вызваны с одним аргументом и не объявлены как
В С++ последовательность преобразований типов может включать не более одного пользовательского преобразования. Однако когда в эту последовательность добавляются встроенные преобразования, ситуация может оказаться предельно запутанной. Решение здесь простое и состоит в следующем.
• По умолчанию используйте explicit в конструкторах с одним аргументом (см. рекомендацию 54):
• Используйте для преобразований типов именованные функции, а не соответствующие операторы:
См. также обсуждение копирующих конструкторов, объявленных как
Пример 1. Перегрузка. Пусть у нас есть, например,
Пример 2. Работающие ошибки. Допустим, вы снабдили класс
В результате этого становятся компилируемыми масса глупостей и опечаток. Пусть
Именно по этой причине в стандартном классе
При нечастом и осторожном использовании неявные преобразования типов могут сделать код более коротким и интуитивно более понятным. Стандартный класс
• Не имеется автоматического преобразования
• Все операторы сравнений, определенные для
Но и при этом возникают определенные неприятности, связанные с перегрузкой функций.
Этот результат для некоторых может оказаться сюрпризом. (Кстати, если бы выполнялся вызов
[Dewhurst03] §36-37 • [Lakos96] §9.3.1 • [Meyers96] §5 • [Murray93] §2.4 • [Sutter00] §6, §20, §39
41. Делайте данные-члены закрытыми (кроме случая агрегатов в стиле структур С)
Данные-члены должны быть закрыты. Только в случае простейших типов в стиле структур языка С, объединяющих в единое целое набор значений, не претендующих на инкапсуляцию и не обеспечивающих поведение, делайте все данные-члены открытыми. Избегайте смешивания открытых и закрытых данных, что практически всегда говорит о бестолковом дизайне.
Сокрытие информации является ключом к качественной разработке программного обеспечения (см. рекомендацию 11). Желательно делать все данные-члены закрытыми; закрытые данные — лучшее средство для сохранения инварианта класса, в том числе при возможных вносимых изменениях.
Открытые данные — плохая идея, если класс моделирует некоторую абстракцию и, следовательно, должен поддерживать инварианты. Наличие открытых данных означает, что часть состояния вашего класса может изменяться неконтролируемо, непредсказуемо и асинхронно с остальной частью состояния. Это означает, что абстракция разделяет ответственность за поддержание одного или нескольких инвариантов с неограниченным множеством кода, который использует эту абстракцию, и совершенно очевидно, что такое положение дел просто недопустимо с точки зрения корректного проектирования.