Expresiones postfijas

Las expresiones de postfijo constan de expresiones primarias o expresiones en las que los operadores de postfijo siguen una expresión primaria. Los operadores de postfijo se enumeran en la tabla siguiente.

Operadores de postfijo

Nombre de operador Notación de operador
Operador de subíndice [ ]
Operador de llamada de función ( )
Operador de conversión explícita de tipos type-name ( )
Operador de acceso a miembros .->,
Operador de incremento de postfijo ++
Operador de decremento de postfijo --

La sintaxis siguiente describe expresiones de postfijo posibles:

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 )

La expresión postfix anterior puede ser una expresión principal u otra expresión de postfijo. Las expresiones de postfijo se agrupan de izquierda a derecha, por lo que las expresiones se pueden encadenar unas a otras del modo siguiente:

func(1)->GetValue()++

En la expresión anterior, es una expresión principal, es una expresión postfija de función, es una expresión de postfijo que especifica un miembro de la clase , es otra expresión postfija de función y toda la expresión es una expresión postfijo que incrementa el valor devuelto func func(1) de func(1)->GetValue func(1)->GetValue() GetValue. El significado de la expresión completa es que la función que llama pasa 1 como argumento y obtiene un puntero a una clase como valor devuelto. A GetValue() continuación, llame a en esa clase y, a continuación, incremente el valor devuelto.

Las expresiones enumeradas anteriormente son expresiones de asignación, lo que significa que el resultado de estas expresiones debe ser un valor R.

La forma de expresión de postfijo

simple-type-name ( expression-list )

indica la invocación del constructor. Si el nombre de tipo simple es un tipo fundamental, la lista de expresiones debe ser una expresión única y esta expresión indica una conversión del valor de la expresión al tipo fundamental. Este tipo de expresión de conversión imita un constructor. Dado que esta forma permite la construcción de tipos y clases fundamentales utilizando la misma sintaxis, es especialmente útil cuando se definen clases de plantilla.

La palabra clave cast-keyword es una de dynamic_cast , o static_cast reinterpret_cast . Puede encontrar más información en dynamic_cast y static_cast reinterpet_cast .

El typeid operador se considera una expresión de postfijo. Vea el operador typeid.

Argumentos formales y reales

Los programas que llaman pasan información a las funciones llamadas en "argumentos reales". Las funciones llamadas tienen acceso a la información mediante el uso de los correspondientes "argumentos formales".

Cuando se llama a una función, se realizan las tareas siguientes:

  • Se evalúan todos los argumentos reales (los proporcionados por el llamador). No hay ningún orden implícito en el que se evalúan estos argumentos, pero se evalúan todos los argumentos y se completan todos los efectos secundarios antes de la entrada a la función.

  • Cada argumento formal se inicializa con su argumento real correspondiente de la lista de expresiones. (Un argumento formal es un argumento que se declara en el encabezado de función y se usa en el cuerpo de una función). Las conversiones se realizan como si se realizara mediante inicialización: las conversiones estándar y definidas por el usuario se realizan al convertir un argumento real al tipo correcto. Inicialización realizada se muestra de forma conceptual en el código siguiente:

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

    Las inicializaciones conceptuales anteriores a la llamada son:

    int Temp_i = 7;
    Func( Temp_i );
    

    Observe que la inicialización se realiza como si se utilizara la sintaxis de signo igual en lugar de la sintaxis de paréntesis. Se realiza una copia de i antes de pasar el valor a la función. (Para obtener más información, vea Inicializadores y conversiones).

    Por lo tanto, si el prototipo de función (declaración) llama a un argumento de tipo y el programa de llamada proporciona un argumento real de tipo , el argumento real se promueve mediante una conversión de tipo estándar al tipo long int long (vea Conversiones estándar).

    Es un error proporcionar un argumento real para el que no hay ninguna conversión estándar o definida por el usuario al tipo del argumento formal.

    Para los argumentos reales de tipo de clase, el argumento formal se inicializa llamando al constructor de la clase. (Vea Constructores para obtener más información sobre estas funciones miembro de clase especiales).

  • Se ejecuta la llamada de función.

El fragmento de programa siguiente muestra una llamada de función:

// 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 )
{
}

Cuando se llama a desde main, el parámetro formal se inicializa con el valor de ( se convierte al tipo para que se corresponda con el tipo correcto mediante una conversión estándar) y el parámetro formal se inicializa con el valor de ( se convierte al tipo mediante una conversión func param1 i i long param2 j j double estándar).

Tratamiento de tipos de argumento

Los argumentos formales declarados const como tipos no se pueden cambiar dentro del cuerpo de una función. Las funciones pueden cambiar cualquier argumento que no sea de tipo const . Sin embargo, el cambio es local para la función y no afecta al valor del argumento real a menos que el argumento real sea una referencia a un objeto que no sea de tipo const .

Las funciones siguientes muestran algunos de estos conceptos:

// 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;
}

Puntos suspensivos y argumentos predeterminados

Las funciones se pueden declarar para aceptar menos argumentos que los especificados en la definición de función, mediante uno de estos dos métodos: puntos suspensivos (...) o argumentos predeterminados.

Los puntos suspensivos indican que los argumentos pueden ser necesarios, pero que el número y los tipos no se especifican en la declaración. Normalmente se considera una mala práctica de programación en C++, porque se frustra una de las ventajas de C++: la seguridad de tipos. Se aplican conversiones diferentes a las funciones declaradas con puntos suspensivos que a las funciones para las que se conocen los tipos de argumento formal y real:

  • Si el argumento real es de tipo float , se promueve al tipo antes de la llamada de double función.

  • Cualquier o , o , tipo enumerado o campo de bits se convierte en un o signed char unsigned char un mediante promoción signed short unsigned short signed int unsigned int integral.

  • Cualquier argumento de tipo de clase se pasa por valor como estructura de datos; la copia se crea mediante copia binaria en lugar de invocar el constructor de copia de clase (si existe).

Los puntos suspensivos, si se usan, deben declararse en último lugar en la lista de argumentos. Para obtener más información sobre cómo pasar un número variable de argumentos, vea la explicación de va_arg, va_start y va_list en la Referencia de biblioteca en tiempo de ejecución.

Para obtener información sobre los argumentos predeterminados en la programación CLR, vea Listas de argumentos variables (...) (C++/CLI).

Los argumentos predeterminados permiten especificar el valor que un argumento debe asumir si no se proporciona ninguno en la llamada a función. El fragmento de código siguiente muestra cómo funcionan los argumentos predeterminados. Para obtener más información sobre las restricciones para especificar argumentos predeterminados, vea Argumentos predeterminados.

// 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;
}

El programa anterior declara una función, print, que toma dos argumentos. Sin embargo, el segundo argumento, terminator, tiene un valor predeterminado, "\n" . En , las dos primeras llamadas a para permitir que el segundo main argumento predeterminado proporcione una nueva línea para finalizar la cadena print impresa. La tercera llamada especifica un valor explícito para el segundo argumento. El resultado del programa es

hello,
world!
good morning, sunshine.

Consulte también

Tipos de expresiones