Анимация
JavaScript
|
Главная Библионтека пример 28-1(6): не С++, но если бы это был он? class if { назовем класс "if" (не разрешено; но • public: если бы это было можно сделать?) if( bool ) {} 3: Гм... конструктор? } > Что означает строка 3? "Это просто, - может сказать кто-то из читателей. - Мы знаем, что условная инструкция в этом месте лишена смыла, причем имя типа не может быть проверяемым условием, так что понятно, что перед нами конструктор. Может, действительно есть определенный смысл в разрешении использовать ключевые слова в качестве имен - в конце концов, не так трудно предположить, что именно они должны означать!" Некоторые из разработчиков языков пошли по этой кривой дорожке... но это очень короткая дорожка! Вы споткнетесь на ней при первой же ситуации наподобие той, что демонстрируется с помощью строк 4 и 5 из следующего исходного текста. пример 28-1(6), продолжение. Вернемся к первоначальному примеру... int main О { if( true ) 4: гмм... и что это означает теперь? if( 42 ); 5: гмм... а это? Что должны означать строки 4 и 5 в этом альтернативном мире? Имеют ли они тот же смысл, что и в рассмотренном нами ранее примере 28-1 я? Или в них используется тип if, который имеет подходящий конструктор, и эти строки означают создание двух безымянных временных объектов? Если вы немного подумаете над этим вопросом, то быстро сообразите, что даже человек не в состоянии точно ответить на него. Чего же тогда ожидать от компилятора там, где пасует даже человек? "Минутку, - может возразить человек, решивший пройти по кривой дорожке до конца, - но ведь можно ввести правило, которое сделает данный код рабочим! Создание временных объектов в строках 4 и 5 только для того, чтобы они тут же были уничтожены, - не слишком полезная вещь, так что мы можем считать, что эго не то, к чему стремился программист, и рассматривать данные строки как обычныс условные инструкции". Я надеюсь, что вы с негодованием отвергнете это решение как непригодный для употребления "хак". Тому есть множество причин. 1. Точно так же легко решить, что запись "if (true);" представляет собой по сути отсутствие операции, что вряд ли являлось целью программиста, так что следует трактовать обе инструкции как объявления временных объектов. 2. Какой бы из вариантов вы ни выбрали, он будет сильно зависеть от того, находится ли класс if в строках 4 и 5 в области видимости или нет. Коротко говоря, наличие таких (скажем прямо - весьма дурно пахнущих) правил в языке следует воспринимать как яркий красный свет, сигнализирующий о серьезных проблемах в дизайне языка. Конечно, есть и другие способы получения неоднозначностей в случае, когда ключевые слова не резервируются. Вот еше один простой случай, который демонстрирует пример 28-1 е. Пример 28-1в: Не С++, но если бы это был он? class someFunctor { public: int operatorO( bool ) { return 42; } SomeFunctor if; назовем переменную "if" вернемся опять к нашему коду... int main О { if( true ); if( 42 ); 6: ГМ... и что это означает? 7: ГМ... а это? Опять же, что должны означать строки 6 и 7? Являются ли они теми обычными условными конструкциями, которые мы так хорошо знаем и с которыми мы уже встречались в примере 28-1 я? Или .здесь используется переменная if, к которой применен оператор operatorO, - и даже с совместимыми аргументами! - и в этом случае инструкции в строках 6 и 7 означают i f .operatorO (true); и if .ope rator О (42);? Я думаю, вполне очевидна невозможность определить, что именно имел в виду программист. Повторяю, это невозможно определить для человека; что уж тогда говорить о компиляторах. Итак, становится ясно, что С++ (как и другие языки программирования) просто вынужден намертво, двухдюймовыми гвоздями прибить значения к некоторым именам. Он вынужден зарезервировать эти имена для собственного использования, поэтому они и называются зарезервированными словами. Ключевые слова С++ Стандарт С++ резервирует в качестве ключевых слов 63 имени, которые перечислены в табл. 28.1. Большинство из этих имен хорошо вам знакомы и ежедневно используются вами. Таблица 28.1. Ключевые слова С++
Кроме того, вместо обычной формы записи, 11 операторов могут использовать запись при помоши слов, например, в условном выражении можно записать and вместо &&. Стандарт резервирует эти слова, так что вы не можете распоряжаться ими для использования в качестве собственных имен. Список этих имен приведен в табл. 28.2. Таблица 28.2. Дополнительные зарезервированные слова not eq and eq or bitand or eq bitor compl xor eq Итого, 74 - посчитайте сами! - определенных имени в ваших программах не могут быть использованы вами произвольным образом, в частности, в качестве имен типов, функций или переменных (см. [С++03, §2.1!]). Зарезервированные комментарии Большинство ключевых слов выполняют какие-то действия. И это правильно - иначе зачем они нужны? Однако некоторые ключевые слова и близко не делают того, на что вы могли бы надеяться. Некоторые из них не имеют никакого семантического влияния на программу вообще, т.е. семантически они эквивалентны пробельным символам, эдаким приукрашенным комментариям. Я имею в виду три ключевых слова - auto, register и, во многих отношениях, inline (см. задачу 25). (Тем, кто удивлен, почему здесь не указано ключевое слово export, могу посоветовать обратиться к задачам 9 и 10.) auto Рассмотрим сначала ключевое слово auto. 2. Как добавление ключевого слова auto изменяет семантику программы на С++? Если говорить коротко: никак, auto - совершенно излишний спецификатор класса памяти. Он появляется только в описаниях локальных объектов (объявленных в блоке кода) и указывает, что эти объекты автоматически уничтожаются при завершении их функции или блока; однако во всех случаях, где допустимо применение auto, предполагается именно такое поведение, если это ключевое слово не указано, что и делает спецификатор auto излишним. То есть, auto означает то же, что и любой пробельный символ. Сейчас нскогорые подкованные читатели стандарта С++ могут громко возразить: "Это не совсем то, что говорит стандарт! В нем всего лишь сказано, что спецификатор auto почти всегда излишен!" И это так: ...спецификатор auto почти всегда излишен и редко используется; одно из предназначений auto - для явного отличия объявления от выражения. - [С++03] §7.1.1 Да, это сказано в стандарте, но это не так (и я уже подал соответствующее сообщение в комитет). Почему? Правило С+ + , которое применяется к таким неоднозначностям, гласит, что все. что может быть объявлением, должно быть объявлением - и добавление auto ничего не меняет. Например: пример 28-2: auto не разрешает неоднозначности. inti; i nt j; int mainO { int(i); объявление i; не ссылка на ::i auto int(j); объявление j. a не ссылка на ::j int f(); объявление функции, a не объект типа int, инициализированный по умолчанию auto int f(); такое же объявление функции, хотя и приведет к ошибке на строгом } компиляторе Более подробно неоднозначность объявлений в С++ рассматривается в задаче 29 (см. также раздел 39 в [MeyersOl]). В итоге auto не может использоваться для разрешения описанных неоднозначностей. > Рекомендация Никогда не используйте auto. Это ключевое слово имеет тот же смысл, что и пробельный символ. Кстати, возможно, в будущем auto будет играть гораздо более важную роль. При работе над очередным стандартом С++ комитет рассматривает вариант применения 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 [ 57 ] 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |