Правило 19: Рассматривайте проектирование класса как проектирование типа
Правило 19: Рассматривайте проектирование класса как проектирование типа
В C++, как и в других объектно-ориентированных языках программирования, при определении нового класса определяется новый тип. Потому большую часть времени вы как разработчик C++ будете тратить на совершенствование вашей системы типов. Это значит, что вы – не просто разработчик классов, но еще и разработчик типов. Перегруженные функции и операторы, управление распределением и освобождением памяти, определение инициализации и порядка уничтожения объектов – все это находится в ваших руках. Поэтому вы должны подходить к проектированию классов так, как разработчики языка подходят к проектированию встроенных типов.
Проектирование хороших классов – ответственная работа, и этим все сказано. Хорошие типы имеют естественный синтаксис, интуитивно воспринимаемую семантику и одну или более эффективных реализаций. В C++ плохо спланированное определение класса может сделать невозможным достижение любой из этих целей. Даже характеристики производительности функций-членов класса могут зависеть от того, как они объявлены.
Итак, как же проектировать эффективные классы? Прежде всего вы должны понимать, с чем имеете дело. Проектирование почти любого класса ставит перед разработчиком вопросы, ответы на которые часто ограничивают спектр возможных решений:
• Как должны создаваться и уничтожаться объекты нового типа? От ответа на этот вопрос зависит дизайн конструкторов и деструкторов, а равно функций распределения и освобождения памяти (оператор new, оператор new[], оператор delete и оператор delete[] – см. главу 8), если вы собираетесь их переопределить.
• Чем должна отличаться инициализация объекта от присваивания значений? Ответ на этот вопрос определяет разницу в поведении между конструкторами и операторами присваивания. Важно не путать инициализацию с присваиванием, потому что им соответствуют разные вызовы функций (см. правило 4).
• Что означает для объектов нового типа быть переданными по значению? Помните, что конструктор копирования определяет реализацию передачи по значению для данного типа.
• Каковы ограничения на допустимые значения вашего нового типа? Обычно только некоторые комбинации значений данных-членов класса являются правильными. Эти комбинации определяют инварианты, которые должен поддерживать класс. А инварианты уже диктуют, как следует контролировать ошибки в функциях-членах, в особенности в конструкторах, операторах присваивания и функциях установки значений («setter» functions). Могут быть также затронуты исключения, которые возбуждают ваши функции, и спецификации этих исключений.
• Укладывается ли ваш новый тип в граф наследования? Наследуя свои классы от других, вы должны следовать ограничениям, налагаемым базовыми классами. В частности, нужно учитывать, как объявлены в них функции-члены: виртуальными или нет (см. правила 34 и 36). Если вы хотите, чтобы вашему классу могли наследовать другие, то нужно тщательно продумать, какие функции объявить виртуальными; в особенности это относится к деструктору (см. правило 7).
• Какие варианты преобразования типов допустимы для вашего нового типа? Ваш тип существует в море других типов, поэтому должны ли быть предусмотрены варианты преобразования между вашим типом и другими? Если вы хотите разрешить неявное преобразование объекта типа T1 в объект типа T2, придется либо написать функцию преобразования в классе T1 (то есть operator T2), либо неявный конструктор в классе T2, который может быть вызван с единственным аргументом. Если же вы хотите разрешить только явные преобразования, то нужно будет написать специальные функции, но ни в коем случае не делать их операторами преобразования или не-explicit конструкторами с одним аргументом. (Примеры явных и неявных функций преобразования приведены в правиле 15.)
• Какие операторы и функции имеют смысл для нового типа? Ответ на этот вопрос определяет набор функций, которые вы объявляете в вашем классе. Некоторые из них будут функциями-членами, другие – нет (см. правила 23, 24 и 46).
• Какие стандартные функции должны стать недоступными? Их надо будет объявить закрытыми (см. правило 6).
• Кто должен получить доступ к членам вашего нового типа? Ответ на этот вопрос помогает определить, какие члены должны быть открытыми (public), какие – защищенными (protected) и какие – закрытыми (private). Также вам предстоит решить, какие классы и/или функции должны быть друзьями класса, а также когда имеет смысл вложить один класс внутрь другого.
• Что такое «необъявленный интерфейс» вашего нового типа? Какого рода гарантии могут быть предоставлены относительно производительности, безопасности относительно исключений (см. правило 29) и использования ресурсов (например, блокировок и динамической памяти)? Такого рода гарантии определяют ограничения на реализацию вашего класса.
• Насколько общий ваш новый тип? Возможно, в действительности вы не определяете новый тип. Возможно, вы определяете целое семейство типов. Если так, то вам нужно определять не новый класс, а новый шаблон класса.
• Действительно ли новый тип представляет собой то, что вам нужно? Если вы определяете новый производный класс только для того, чтобы расширить функциональность существующего класса, то, возможно, этой цели лучше достичь простым определением одной или более функций-нечленов либо шаблонов.
На эти вопросы нелегко ответить, поэтому определение эффективных классов – непростая задача. Но при ее должном выполнении определенные пользователями классы C++ дают типы, которые ничем не уступают встроенным и уже оправдывают все ваши усилия.
Что следует помнить
• Проектирование класса – это проектирование типа. Прежде чем определять новый тип, убедитесь, что рассмотрены все вопросы, которые обсуждаются в настоящем правиле.
Более 800 000 книг и аудиокниг! 📚
Получи 2 месяца Литрес Подписки в подарок и наслаждайся неограниченным чтением
ПОЛУЧИТЬ ПОДАРОКДанный текст является ознакомительным фрагментом.
Читайте также
Проектирование сети
Проектирование сети Проектирование сети – важнейший этап в ее создании, который ни в коем случае нельзя пропускать, иначе можно ошибиться в расчетах, что повлечет лишние денежные затраты. Если на фоне крупного предприятия это не так критично (лишние запчасти никогда
Проектирование сети
Проектирование сети Проектирование играет огромную роль в любом начинании. Представьте себе, что автомобили создавались сразу же или многоэтажные дома строили безо всякого проекта. Насколько надежными были бы эти вещи? Ответ очевиден.Что касается сети, то
Проектирование здания
Проектирование здания Рассмотрим простой пример, в котором создадим стандартный проект с помощью специального мастера House Builder Wizard (Мастер строительства дома).Откройте программу 3D Home Architect Design Suite Deluxe и вызовите мастер, щелкнув кнопкой мыши на запускающем программу
8.2. Проектирование
8.2. Проектирование Архитектурный каркас Каждая программная система должна иметь простую и в то же время всеобъемлющую организационную философию. Система мониторинга погоды не является в этом смысле исключением. На следующем этапе нашей работы мы должны четко
9.2. Проектирование
9.2. Проектирование Тактические вопросы В соответствии с законом разработки программ Коггинса "прагматизм всегда должен быть предпочтительней элегантности, ведь Природу все равно ничем не удивить". Следствие: проектирование никогда не будет полностью независимым от
10.2. Проектирование
10.2. Проектирование Формулируя подходы к архитектуре системы складского учета, мы должны помнить о трех моментах организационного характера: разделение функций между клиентской и серверной частью, механизм управления транзакциями, стратегия реализации клиентской
11.2. Проектирование
11.2. Проектирование Архитектура информационной доски Теперь у нас есть все, чтобы приступить к решению поставленной задачи с использованием метафоры информационной доски. Это классический пример повторного использования "в большом": мы повторно применяем испытанный
12.2. Проектирование
12.2. Проектирование Как уже отмечалось в главе 6, создание архитектуры подразумевает выявление основной структуры классов и спецификацию общих взаимодействий, которые оживляют классы. Сконцентрировав внимание прежде всего на этих механизмах, мы с самого начала выявляем
Проектирование балок
Проектирование балок Следующий инструмент проектирования строительных конструкций – балки. Для активизации этого инструмента щелкните на кнопке Beam (Балка) раздела Design (Проектирование) палитры ToolBox (Палитра инструментов). Основные параметры балок отобразятся на
Проектирование дверей
Проектирование дверей Для создания дверей в ArchiCAD существует специальный инструмент, кнопка активизации которого – Door (Дверь) – находится на палитре ToolBox (Палитра инструментов). При щелчке на этой кнопке на информационной палитре появляются параметры данного объекта
Проектирование окон
Проектирование окон Для проектирования окон существует отдельный инструмент, кнопка активизации которого – Window (Окно) – расположена на палитре ToolBox (Палитра инструментов). При щелчке на этой кнопке на информационной палитре появляются настройки окна (рис. 5.8). Рис. 5.8.
Проектирование лестниц
Проектирование лестниц Переходим к одному из самых интересных объектов библиотеки ArchiCAD – лестницам. Интересен он не только потому, что существует достаточно большое количество видов этого объекта и выбор лестницы с настройкой ее параметров превращается в
Интерфейсы и проектирование ПО
Интерфейсы и проектирование ПО Архитектура системы должна основываться на содержании, а не на форме. Но проектирование сверху вниз стремится использовать в качестве основы для структуры самый поверхностный аспект системы - ее внешний интерфейс. Такой упор на внешний
У8.3 Проектирование нотации
У8.3 Проектирование нотации Предположим, вы часто используете сравнение в форме x.is_equal (y), и хотите упростить нотацию, используя преимущества инфиксной записи (применимой здесь, поскольку наша функция имеет один аргумент). Для инфиксного компонента используйте некоторый
Проектирование
Проектирование Ключевым аспектом развертывания PKI является выбор архитектуры и проектирование. PKI допускает гибкость проектирования независимо от выбранной технологии. Этап проектирования занимает длительное время, так как на этом этапе должна быть сформирована