Выражения
Как уже было упомянуто в предыдущих главах (в истории ООП), одним из наиболее значимых нововведений языков программрования высокого уровня, стала возможность записи арифметических выражений в естественной для человека форме, с использованием операторов и функций. Для того чтобы посчитать значение выражения, теперь программисту требуется лишь правильно записать его, не заботясь о том, как оно будет вычисляться. Всю работу по разбору такого выражения, определению очередности выполнения операций берет на себя компилятор языка.
В этой главе мы узнаем, что такое выражения с точки зрения языка К++, как они формируются и на что нужно обращать внимание при их записи. Кратко будет затронута тема операторов, будут даны основные сведения о них. Более подробно, операторы как элемент языка К++, будут рассмотрены в конце книги, в отдельном разделе.
Арифметические операции
Наиболее простой и понятный тип выражений — это самые обычные арифметические выражения:
<source lang="kpp"> var x = 2 + 3 * 4; var y = (2 + 3) * 4; </source>
Для простоты мы используем хорошо нам известную конструкцию объявления переменной, но на этот раз в инициализаторе мы указываем не одну константу, вроде строки "hello world", а целое выражение. Выражением считается все, что записано между знаком "=" и точкой с запятой ";", которая завершает конструкцию.
При вычислении значения выражения применяются те же самые правила что и в обычной математике, то есть операции имеют приоритет и выполняются строго в порядке убывания приоритета. В первом случае, сначала будет вычислено подвыражение 3 * 4, к значению которого будет добавлено число 2; сумма будет установлена как значение переменной. Во втором случае, приоритет операций был изменен введением круглых скобок, которые имеют тот же смысл, что и в математике: сначала вычисляется значение в скобках, а затем остальные операции, опять же в порядке их приоритета. Скобок в выражение может быть сколько угодно, допускается вложенность.
...Таким образом, переменной x будет присвоено значение 14, а переменная y будет равна 20.
В выражениях могут указываться не только числовые константы. Так же как и в математике, в выражениях можно использовать переменные.
При вычислении выражения вмсето имени переменной подставляется ее значение. Таким образом, если в ходе рассчетов выражения, переменная изменит свое значение, то вместе следующего вхождения переменной может быть подставлено уже новое значение. А чтобы с уверенностью сказать "может быть подставлено" или "будет подставлено" нужно смотреть, какой именно код записан в выражении. С этим моментом связана известная проблема неоднозначности выражений. Забежав вперед, можно рассмотреть связанный с данным вопросом пример применения операторов в выражении:
<source lang="kpp"> var i = 5; var x = ++i + ++i; </source>
Как вы думаете, какое значение будет иметь переменная x после выполнения вышеприведенного кода? Программист, знающий только Паскаль при виде этого примера скорее всего впадет в ступор, поскольку этот язык не имеет оператора ++, либо он сочтет что выражение записано ошибочно.
Новичок, изучающий язык C++, но уже кое-что знающий о нем, может рассуждать так: «Оператор ++ — это оператор инкремента. В зависимости от того где он расположен в выражении, будет зависеть то как он изменяет переменную; если оператор находится слева он переменной, то сначала будет произведена операция инкремента, а затем новое значение будет использоваться при расчете выражения. В нашем случае это именно так. Стало быть, при рассчете выражения, в обоих случаях значение переменной i будет увеличено на единицу и будет использовано в рассчете. В результате мы получим выражение x = 6 + 6 = 12»
Другой новичок может возразить ему и сказать, что при вычислении выражения должно подставляться фактическое значение переменной на текущий момент. Значит, в качестве первого слагаемого надо брать число 5 + 1, то есть 6, а в качестве второго 6 + 1, то есть 7. В итоге получаем выражение 6 + 7 = 13.
Опытный программист на C++, первым делом спросит как реализован оператор ++, и происходит ли копирование переменной. Если копирование происходит, то значение будет таким же как у первого новичка, то есть 12. Если же оператор работает с самой переменной, то произойдет следующее:
Первый оператор ++ увеличит значение переменной i на единицу, которое теперь будет равно 6. Поскольку мы имеем дело со ссылкой на переменную то это значение не будет нигде сохраняться. Далее, при вычислении значения второго слагаемого сработает уже второй оператор ++, который так же увеличит (уже увеличенное значение!) переменную на 1, и вернет результат 6 + 1, то есть 7. При вычислении итогового значения мы получаем выражение 7 + 7, то есть 14.
Получается что сколько человек, столько и мнений. А самое интересное, что каждый из них прав. Их рассуждения логичны с учетом того, с какой позиции смотреть на проблему. В такой неразберихе запутаться. Если читатель еще не сбит с толку окончательно, то можно продолжить и рассмотреть эту задачу с точки зрения языка К++.
Вызов функций
Вызов функций в выражениях осуществляется путем записи имени функции, следом за которым в круглых скобках перечисляются ее аргументы. Если функуция не принимает параметров, либо все параметры имеют значения по умолчанию, то скобки можно опустить. При этом, при вычислении выражения, вместо самой функции будет подставлено ее значение:
<source lang="kpp"> const pi = 3.1415926; var x = 10; var y = x * sin(pi); </source>
Доступ к полям
Доступ к полям и свойствам классов осуществляется путем записи имени объекта, следом закоторым ставится оператор точка ".", а затем идентификатор поля либо метода. Если ссылаемое поле само имеет свойства или поля, то к ним так же можно ссылаться, поставив вторую точку и указав идентификатор и т. д.
<source lang="kpp" line="1"> class MyClass {
var m_Field = "hello world"; property field read m_Field write m_Field; public function SetField(const string what = "world") { m_Field = "hello " + what; }
}
function caller() {
var object = new MyClass; println(object.field); object.field = "hello everyone!"; object.SetField("universe"); object.SetField;
} </source>
- 1-7
- Мы объявляем некоторый класс MyClass, который имеет поле m_Field и свойство field, связанное с полем. Так же имеется метод SetField(), который устанавливает новое значение свойства, которое определяется выражением в строке 5. Значение свойства складывается из строковой константы "hello ", к которой добавляется значение параметра what.