Читаем Эффективное использование C++. 55 верных способов улучшить структуру и код ваших программ полностью

Это практически такой же подход, как и прежде, за исключением того, что тело чисто виртуальной функции Airplane::fly заменяет собой независимую функцию Airplane::defaultFly. По существу, fly разбита на две основные составляющие. Объявление задает интерфейс (который должен быть использован в производных классах), а определение задает поведение по умолчанию (которое может использоваться производным классом, но только по явному требованию). Однако, производя слияние fly и defaultFly, мы теряем возможность задать для этих функций разные уровни доступа: код, который должен быть защищенным (функция defaultFly), становится открытым (потому что теперь он находится внутри fly).

И наконец, пришла очередь невиртуальной функции класса Shape – objectID:

class Shape {

public:

int objectID() const;

...

};

Когда функция-член объявлена невиртуальной, не предполагается, что она будет вести себя иначе в производных классах. В действительности невиртуальные функции-члены выражают инвариант относительно специализации, поскольку определяют поведение, которое должно сохраняться независимо от того, как специализируются производные классы. Справедливо следующее:

• Цель объявления невиртуальной функции – заставить производные классы наследовать как ее интерфейс, так и обязательную реализацию.

Вы можете представлять себе объявление Shape::objectID как утверждение: «Каждый объект Shape имеет функцию, которая дает идентификатор объекта, и этот идентификатор всегда вычисляется одним и тем же способом. Этот способ задается определением функции Shape::objectID, и никакой производный класс не должен его изменять». Поскольку невиртуальная функция определяет инвариант относительно специализации, ее не следует переопределять в производных классах (см. правило 36).

Разница в объявлениях чисто виртуальных, просто виртуальных и невиртуальных функций позволяет точно указать, что, по вашему замыслу, должны наследовать производные классы: только интерфейс, интерфейс и реализацию по умолчанию либо интерфейс и обязательную реализацию соответственно. Поскольку эти типы объявлений обозначают принципиально разные вещи, следует тщательно подходить к выбору подходящего варианта при объявлянии функции-члена. При этом вы должны избегать двух ошибок, чаще всего совершаемых неопытными проектировщиками классов.

Первая ошибка – объявление всех функций невиртуальными. Это не оставляет возможности для маневров в производных классах; при этом больше всего проблем вызывают невиртуальные деструкторы (см. правило 7). Конечно, нет ничего плохого в проектировании классов, которые не предполагается использовать в качестве базовых. В этом случае вполне уместен набор из одних только невиртуальных функций-членов. Однако очень часто такие классы объявляются либо из-за незнания различий между виртуальными и невиртуальными функциями, либо в результате необоснованного беспокойства по поводу потери производительности при использовании виртуальных функций. Факт остается фактом: практически любой класс, который должен использоваться как базовый, будет содержать виртуальные функции (см. правило 7).

Если вы обеспокоены тем, во что обходится использование виртуальных функций, позвольте мне напомнить вам эмпирическое правило «80–20» (см. также правило 30), которое утверждает, что в типичной программе 80 % времени исполнения затрачивается на 20 % кода. Это правило крайне важно, потому что оно означает, что в среднем 80 % ваших функций могут быть виртуальными, не оказывая ощутимого влияния на общую производительность программы. Прежде чем начать беспокоиться о том, можете ли вы позволить себе использование виртуальных функций, убедитесь, что вы имеете дело с теми 20 % программы, для которых ваше решение окажет существенное влияние на производительность.

Другая распространенная ошибка – объявление всех функций виртуальными. Иногда это правильно, о чем свидетельствуют, например, интерфейсные классы (см. правило 31). Однако данное решение может также навести на мысль, что у разработчика нет ясного понимания задачи. Некоторые функции не должны переопределяться в производных классах, и в таком случае необходимо недвусмысленно указать на это, объявляя функции невиртуальными. Не имеет смысла делать вид, что ваш класс годится на все случаи жизни, стоит лишь переопределить его функции. Если вы видите необходимость в инвариантности относительно специализации, не бойтесь это признать!

Что следует помнить

• Наследование интерфейса отличается от наследования реализации. При открытом наследовании производные классы всегда наследуют интерфейсы базовых классов.

• Чисто виртуальные функции означают, что наследуется только интерфейс.

• Обычные виртуальные функции означают, что наследуются интерфейс и реализация по умолчанию.

• Невиртуальные функции означают, что наследуются интерфейс и обязательная реализация.

Перейти на страницу:

Похожие книги

1С: Управление торговлей 8.2
1С: Управление торговлей 8.2

Современные торговые предприятия предлагают своим клиентам широчайший ассортимент товаров, который исчисляется тысячами и десятками тысяч наименований. Причем многие позиции могут реализовываться на разных условиях: предоплата, отсрочка платежи, скидка, наценка, объем партии, и т.д. Клиенты зачастую делятся на категории – VIP-клиент, обычный клиент, постоянный клиент, мелкооптовый клиент, и т.д. Товарные позиции могут комплектоваться и разукомплектовываться, многие товары подлежат обязательной сертификации и гигиеническим исследованиям, некондиционные позиции необходимо списывать, на складах периодически должна проводиться инвентаризация, каждая компания должна иметь свою маркетинговую политику и т.д., вообщем – современное торговое предприятие представляет живой организм, находящийся в постоянном движении.Очевидно, что вся эта кипучая деятельность требует автоматизации. Для решения этой задачи существуют специальные программные средства, и в этой книге мы познакомим вам с самым популярным продуктом, предназначенным для автоматизации деятельности торгового предприятия – «1С Управление торговлей», которое реализовано на новейшей технологической платформе версии 1С 8.2.

Алексей Анатольевич Гладкий

Финансы / Программирование, программы, базы данных
Язык программирования C++. Пятое издание
Язык программирования C++. Пятое издание

Лучшее руководство по программированию и справочник по языку, полностью пересмотренное и обновленное под стандарт С++11!Р'С‹ держите в руках новое издание популярного и исчерпывающего бестселлера по языку программирования С++, которое было полностью пересмотрено и обновлено под стандарт С++11. Оно поможет вам быстро изучить язык и использовать его весьма эффективными и передовыми способами. Р' соответствии с самыми передовыми и современными методиками изложения материала авторы демонстрируют использование базового языка и его стандартной библиотеки для разработки эффективного, читабельного и мощного кода.С самого начала этой книги читатель знакомится со стандартной библиотекой С++, ее самыми популярными функциями и средствами, что позволяет сразу же приступить к написанию полезных программ, еще не овладев всеми нюансами языка. Большинство примеров из книги было пересмотрено так, чтобы использовать новые средства языка и продемонстрировать РёС… наилучшие СЃРїРѕСЃРѕР±С‹ применения. Эта книга — не только проверенное руководство для новичков в С++, она содержит также авторитетное обсуждение базовых концепций и методик языка С++ и является ценным ресурсом для опытных программистов, особенно желающих побыстрей узнать об усовершенствованиях С++11.Стенли Р'. Липпман работал старшим консультантом в Jet Propulsion Laboratory, архитектором РіСЂСѓРїРїС‹ Visual С++ корпорации Microsoft, техническим сотрудником Bell Laboratories и главным инженером- программистом по анимации в кинокомпаниях Disney, DreamWorks, Pixar и PDI.Р–РѕР·и Лажойе, работающий ныне в кинокомпании Pixar, был членом канадской РіСЂСѓРїРїС‹ разработчиков компилятора C/C++ корпорации IBM, а также возглавлял рабочую группу базового языка С++ в составе международной организации по стандартизации ANSI/ISO.Барбара Э. Му имеет почти тридцатилетний опыт программирования. На протяжении пятнадцати лет она работала в компании AT&T, сотрудничая с Бьярне Страуструпом, автором языка С++, и несколько лет руководила РіСЂСѓРїРїРѕР№ разработчиков С++.• Узнайте, как использовать новые средства языка С++11 и стандартной библиотеки для быстрого создания надежных программ, а также ознакомьтесь с высокоуровневым программированием• Учитесь на примерах, в которых показаны передовые стили программирования и методики проектирования• Р

Барбара Э. Му , Жози Лажойе , Стенли Б. Липпман

Программирование, программы, базы данных
97 этюдов для архитекторов программных систем
97 этюдов для архитекторов программных систем

Успешная карьера архитектора программного обеспечения требует хорошего владения как технической, так и деловой сторонами вопросов, связанных с проектированием архитектуры. В этой необычной книге ведущие архитекторы ПО со всего света обсуждают важные принципы разработки, выходящие далеко за пределы чисто технических вопросов.?Архитектор ПО выполняет роль посредника между командой разработчиков и бизнес-руководством компании, поэтому чтобы добиться успеха в этой профессии, необходимо не только овладеть различными технологиями, но и обеспечить работу над проектом в соответствии с бизнес-целями. В книге более 50 архитекторов рассказывают о том, что считают самым важным в своей работе, дают советы, как организовать общение с другими участниками проекта, как снизить сложность архитектуры, как оказывать поддержку разработчикам. Они щедро делятся множеством полезных идей и приемов, которые вынесли из своего многолетнего опыта. Авторы надеются, что книга станет источником вдохновения и руководством к действию для многих профессиональных программистов.

Билл де Ора , Майкл Хайгард , Нил Форд

Программирование, программы, базы данных / Базы данных / Программирование / Книги по IT