Эффективный и современный С++. 42 рекомендации по использованию С++11 и С++14 - [31]

Шрифт
Интервал

>  primeFactors(c);              // значения Color (!)

>}

Добавление простого ключевого слова >class после >enum преобразует перечисление без области видимости в перечисление с областью видимости, и это — совсем другая история. Не имеется никаких неявных преобразований элементов перечисления с областью видимости в любой другой тип:

>enum class Color      // Перечисление с областью видимости

> {black, white, red};


>Color с = Color::red; // Как и ранее, но с квалификатором

>                      // области видимости

>if (с < 14.5) {       // Ошибка! Нельзя сравнивать

>                      // Color и double

> auto factors =       // Ошибка! Нельзя передавать Color в

>  primeFactors(c);    // функцию, ожидающую std::size_t

>}

Если вы хотите честно выполнить преобразование из >Color в другой тип, сделайте то же, что вы всегда делаете для осуществления своих грязных желаний, — воспользуйтесь явным приведением типа:

>if (static_cast(c) < 14.5) { // Странный, но

>                                     // корректный код

> auto factors =       // Сомнительно, но компилируется

>  primeFactors (static_cast(c));

>}

Может показаться, что перечисления с областями видимости имеют и третье преимущество перед перечислениями без областей видимости, поскольку могут быть предварительно объявлены, их имена могут быть объявлены без указания перечислителей:

>enum Color;       // Ошибка!

>enum class Color; // OK

Это заблуждение. В С++11 перечисления без областей видимости также могут быть объявлены предварительно, но только с помощью небольшой дополнительной работы, которая вытекает из того факта, что каждое перечисление в С++ имеет целочисленный базовый тип (underlying type), который определяется компилятором. Для перечисления без области видимости наподобие >Color

>enum Color { black, white, red };

компилятор может выбрать в качестве базового типа >char, так как он должен представить всего лишь три значения. Однако некоторые перечисления имеют куда больший диапазон значений, например:

>enum Status { good = 0,

>              failed = 1,

>              incomplete = 100,

>              corrupt = 200,

>              indeterminate = 0xFFFFFFFF

>};

Здесь должны быть представлены значения в диапазоне от >0 до >0xFFFFFFFF. За исключением необычных машин (где >char состоит как минимум из 32 битов), компилятор выберет для предоставления значений >Status целочисленный тип, больший, чем >char.

Для эффективного использования памяти компиляторы часто выбирают наименьший базовый тип, которого достаточно для представления значений перечислителей. В некоторых случаях, когда компиляторы выполняют оптимизацию по скорости, а не по размеру, они могут выбрать не наименьший допустимый тип, но при этом они, определенно, захотят иметь возможность оптимизации размера. Для этого С++98 поддерживает только определения >enum (в которых перечислены все значения); объявления >enum не разрешены. Это позволяет компиляторам выбирать базовый тип для каждого >enum до его использования.

Но невозможность предварительного объявления >enum имеет свои недостатки. Наиболее важным из них, вероятно, является увеличение зависимостей при компиляции. Вновь обратимся к перечислению >Status:

>enum Status { good = 0,

>              failed = 1,

>              incomplete = 100,

>              corrupt = 200,

>              indeterminate = 0xFFFFFFFF

>};

Это разновидность перечисления, которая, скорее всего, будет использоваться во всей системе, а следовательно, включенная в заголовочный файл, от которой зависит каждая из частей системы. Если добавить новое значения состояния

>enum Status { good = 0,

>              failed = 1,

>              incomplete = 100,

>              corrupt = 200,

>              audited = 500,

>              indeterminate = 0xFFFFFFFF

>};

то, вероятно, придется перекомпилировать всю систему полностью, даже если только одна подсистема — возможно, одна-единственная функция! — использует это новое значение. Это одна из тех вещей, которые программисты просто ненавидят. И это та вещь, которую исключает возможность предварительного объявления >enum в С++11. Например, вот совершенно корректное объявление >enum с областью видимости, и функции, которая получает его в качестве параметра:

>enum class Status;                 // Предварительное объявление

>void continueProcessing(Status s); // и его использование

Заголовочный файл, содержащий эти объявления, не требует перекомпиляции при пересмотре определения >Status. Кроме того, если изменено перечисление >Status (например, добавлено значение >audited), но поведение >continueProcessing не изменилось (например, потому что >continueProcessing не использует значение >audited), то не требуется и перекомпиляция реализации >continueProcessing.

Но если компилятор должен знать размер >enum до использования, то как могут перечисления С++ 11 быть предварительно объявлены, в то время как перечисления С++98 этого не могут? Ответ прост: базовый тип перечислений с областью видимости всегда известен, а для перечислений без областей видимости вы можете его указать.

По умолчанию базовым типом для >enum с областью видимости является


Еще от автора Скотт Мейерс
Эффективное использование STL

В этой книге известный автор Скотт Мейерс раскрывает секреты настоящих мастеров, позволяющие добиться максимальной эффективности при работе с библиотекой STL.Во многих книгах описываются возможности STL, но только в этой рассказано о том, как работать с этой библиотекой. Каждый из 50 советов книги подкреплен анализом и убедительными примерами, поэтому читатель не только узнает, как решать ту или иную задачу, но и когда следует выбирать то или иное решение — и почему именно такое.


Как функции, не являющиеся методами, улучшают инкапсуляцию

Когда приходится инкапсулировать, то иногда лучше меньше, чем большеЯ начну со следующего утверждения: Если вы пишете функцию, которая может быть выполнена или как метод класса, или быть внешней по отношению к классу, Вы должны предпочесть ее реализацию без использования метода. Такое решение увеличивает инкапсуляцию класса. Когда Вы думаете об использовании инкапсуляции, Вы должны думать том, чтобы не использовать методы.Удивлены? Читайте дальше.


Рекомендуем почитать
Изучаем Java EE 7

Java Enterprise Edition (Java EE) остается одной из ведущих технологий и платформ на основе Java. Данная книга представляет собой логичное пошаговое руководство, в котором подробно описаны многие спецификации и эталонные реализации Java EE 7. Работа с ними продемонстрирована на практических примерах. В этом фундаментальном издании также используется новейшая версия инструмента GlassFish, предназначенного для развертывания и администрирования примеров кода. Книга написана ведущим специалистом по обработке запросов на спецификацию Java EE, членом наблюдательного совета организации Java Community Process (JCP)


Платформа J2Me

Эта книга научит вас, как разрабатывать программное обеспечение для платформы J2ME компании «Sun Microsystems». Эта книга придерживается стиля учебного пособия, это не справочное руководство.Цель — дать вам твердую основу в понятиях и техниках, которая даст вам возможность решиться на самостоятельную разработку качественных приложений.


Виртуальная библиотека Delphi

В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.


Обработка баз данных на Visual Basic.NET

Это практическое руководство разработчика программного обеспечения на Visual Basic .NET и ADO.NET, предназначенное для создания приложений баз данных на основе WinForms, Web-форм и Web-служб. В книге описываются практические способы решения задач доступа к данным, с которыми сталкиваются разработчики на Visual Basic .NET в своей повседневной деятельности. Книга начинается с основных сведений о создании баз данных, использовании языка структурированных запросов SQL и системы управления базами данных Microsoft SQL Server 2000.


Исчерпывающее руководство по написанию всплывающих подсказок

В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.


Программное обеспечение встроенных систем. Общие требования к разработке и документированию

Embedded system software. General requirements for development and documentationСтандарт подготовлен в развитие ГОСТ Р ИСО/МЭК 12207-99 «Информационная технология. Процессы жизненного цикла программных средств» с целью учета специфики разработки и документирования программного обеспечения встроенных систем реального времени.