Постфиксные выражения

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

Постфиксные операторы

Имя оператора Нотация оператора
Оператор subscript [ ]
Оператор вызова функции ( )
Оператор явного преобразования типов type-name( )
Оператор доступа к членам . или ->
Оператор добавочного увеличения postfix ++
Оператор декремента postfix --

Следующий синтаксис описывает возможные постфиксные выражения:

primary-expression
postfix-expression[expression]postfix-expression(expression-list)simple-type-name(expression-list)postfix-expression.namepostfix-expression->namepostfix-expression++postfix-expression--cast-keyword < typename > (expression )typeid ( typename )

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

func(1)->GetValue()++

В приведенном выше выражении func является первичным выражением, func(1) является выражением постфикса функции, func(1)->GetValue является выражением postfix, указывающим член класса, является другим выражением постфикса функции, func(1)->GetValue() и все выражение является выражением постфикса, добавив возвращаемое значение GetValue. Значение выражения в целом имеет следующий смысл: "вызовите функцию, передающую 1 в качестве аргумента, и получите указатель на класс в качестве возвращаемого значения. Затем вызовите этот класс, а затем увеличьте GetValue() возвращаемое значение.

Перечисленные выше выражения — это выражения присваивания, что означает, что результат этих выражений должен представлять собой r-значение.

Форма постфиксного выражения

simple-type-name ( expression-list )

показывает вызов конструктора. Если simple-type-name — это фундаментальный тип, список выражений должен представлять собой отдельное выражение, и это выражение обозначает приведение значения выражения к фундаментальному типу. Данный тип выражения приведения копирует конструктор. Поскольку эта форма позволяет создавать фундаментальные типы и классы с использованием одного и того же синтаксиса, эта форма особенно полезна при определении шаблонных классов.

Приведение ключевое слово является одним из dynamic_castили static_castreinterpret_cast. Дополнительные сведения можно найти в dynamic_cast, static_cast а reinterpet_castтакже .

Оператор typeid считается выражением постфикса. См . оператор typeid.

Формальные и фактические аргументы

Вызовы программ передают информацию вызываемой функции в "фактических аргументах". Вызываемые функции получают доступ к информации с помощью соответствующих "формальных аргументов".

При вызове функции выполняются следующие задачи.

  • Вычисляются все фактические аргументы (предоставляемые вызывающим объектом). Эти аргументы вычисляются в произвольном порядке, но все аргументы вычисляются и все побочные эффекты завершаются перед переходом в функцию.

  • Каждый формальный аргумент инициализируется с соответствующим фактическим аргументом в списке выражений. (Формальный аргумент — это аргумент, объявленный в заголовке функции и используемый в тексте функции.) Преобразования выполняются так, как будто путем инициализации — при преобразовании фактического аргумента в правильный тип выполняются как стандартные, так и определяемые пользователем преобразования. В общем виде выполненная инициализация показана в следующем коде.

    void Func( int i ); // Function prototype
    ...
    Func( 7 );          // Execute function call
    

    Ниже представлены концептуальные инициализации до вызова.

    int Temp_i = 7;
    Func( Temp_i );
    

    Обратите внимание, что инициализация выполняется таким образом, как если бы использовался синтаксис со знаком равенства, а не синтаксис с круглыми скобками. Копия i создается до передачи значения в функцию. (Дополнительные сведения см. в разделе Инициализаторы и преобразования).

    Таким образом, если прототип функции (объявление) вызывает аргумент типа и если вызывающая программа предоставляет фактический аргумент типаlongint, фактический аргумент повышен с помощью стандартного преобразования типов в тип long (см. стандартные преобразования).

    Предоставление фактического аргумента при отсутствии стандартного или пользовательского преобразования в тип формального аргумента будет ошибкой.

    В случае фактических аргументов типа класса формальный аргумент инициализируется путем вызова конструктора класса. (См. раздел Конструкторы для получения дополнительных данных об этих функциях-членах класса.)

  • Выполняется вызов функции.

В следующем фрагменте программного кода показан вызов функции.

// expre_Formal_and_Actual_Arguments.cpp
void func( long param1, double param2 );

int main()
{
    long i = 1;
    double j = 2;

    // Call func with actual arguments i and j.
    func( i, j );
}

// Define func with formal parameters param1 and param2.
void func( long param1, double param2 )
{
}

При func вызове из main формальный параметр param1 инициализируется со значением i (i преобразуется в тип long для соответствия правильному типу с помощью стандартного преобразования), а формальный параметр param2 инициализируется со значением j (j преобразуется в тип double с помощью стандартного преобразования).

Работа с типами аргументов

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

Некоторые из этих понятий показаны на примере следующих функций.

// expre_Treatment_of_Argument_Types.cpp
int func1( const int i, int j, char *c ) {
   i = 7;   // C3892 i is const.
   j = i;   // value of j is lost at return
   *c = 'a' + j;   // changes value of c in calling function
   return i;
}

double& func2( double& d, const char *c ) {
   d = 14.387;   // changes value of d in calling function.
   *c = 'a';   // C3892 c is a pointer to a const object.
    return d;
}

Многоточие и аргументы по умолчанию

Чтобы функции принимали меньше аргументов, чем указано в определении функции, их можно определять, используя многоточие (...) или аргументы по умолчанию.

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

  • Если фактический аргумент имеет типfloatdouble, он повышен до вызова функции.

  • Любое signed char или unsigned charsigned shortunsigned shortперечисленное или перечисленное поле или битовое поле преобразуется в одно signed int или целочисленное unsigned int повышение.

  • Любой аргумент типа класса передается по значению в виде структуры данных; копия создается путем двоичного копирования, а не путем вызова конструктора копии класса (если он имеется).

Многоточие, если используется, должно быть объявлено последним в списке аргументов. Дополнительные сведения о передаче переменного числа аргументов см. в обсуждении va_arg, va_start и va_list в справочнике по библиотеке времени выполнения.

Сведения о аргументах по умолчанию в программировании среды CLR см. в статьях "Списки аргументов переменных" (...) (C++/CLI).

Аргументы по умолчанию позволяют задать значение, которое должен принять аргумент, если в вызове функции значение не передано. В следующем фрагменте кода показано, как работают аргументы по умолчанию. Дополнительные сведения об ограничениях на указание аргументов по умолчанию см. в разделе "Аргументы по умолчанию".

// expre_Ellipsis_and_Default_Arguments.cpp
// compile with: /EHsc
#include <iostream>

// Declare the function print that prints a string,
// then a terminator.
void print( const char *string,
            const char *terminator = "\n" );

int main()
{
    print( "hello," );
    print( "world!" );

    print( "good morning", ", " );
    print( "sunshine." );
}

using namespace std;
// Define print.
void print( const char *string, const char *terminator )
{
    if( string != NULL )
        cout << string;

    if( terminator != NULL )
        cout << terminator;
}

Представленная выше программа объявляет функцию print, принимающую два аргумента. Однако второй аргумент, терминатор, имеет значение "\n"по умолчанию. В mainпервых двух вызовах, позволяющих print второму аргументу по умолчанию предоставить новую строку для завершения печатной строки. В третьем вызове указывается явное значение второго аргумента. После выполнения этой программы выводится следующий результат:

hello,
world!
good morning, sunshine.

См. также

Типы выражений