Expressions suffixées

Les expressions suffixées se composent d'expressions primaires ou d'expressions dans lesquelles les opérateurs suffixés suivent une expression primaire. Les opérateurs suffixés sont répertoriées dans le tableau suivant.

Opérateurs suffixés

Nom de l’opérateur Notation de l'opérateur
Opérateur d’indice [ ]
Opérateur d’appel de fonction ( )
Opérateur de conversion de type explicite type-name( )
Opérateur d’accès aux membres . ou ->
Opérateur d’incrément postfix ++
Opérateur de décrémentation Postfix --

La syntaxe suivante décrit les expressions suffixées possibles :

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 )

L’expression postfix-ci-dessus peut être une expression primaire ou une autre expression postfix. Les expressions suffixées sont regroupées de gauche à droite. Elles peuvent ainsi être chaînées les unes aux autres comme suit :

func(1)->GetValue()++

Dans l’expression ci-dessus, func est une expression primaire, func(1) est une expression postfix de fonction, func(1)->GetValue est une expression postfix spécifiant un membre de la classe, func(1)->GetValue() est une autre expression de postfix de fonction, et l’expression entière est une expression postfix incrémentant la valeur de retour de GetValue. L’expression entière signifie : Appeler fonction passant 1 comme argument et obtenir un pointeur vers une classe comme valeur de retour. Appelez GetValue() ensuite cette classe, puis incrémentez la valeur retournée.

Les expressions répertoriées ci-dessus sont des expressions d'assignation, ce qui signifie que le résultat de ces expressions doit être une r-value.

Forme de l'expression suffixée

simple-type-name ( expression-list )

indique l'appel du constructeur. Si le nom-type-simple est un type fondamental, la liste d'expressions doit être une expression unique, et cette expression montre un cast de la valeur de l'expression au type fondamental. Ce type d'expression de cast simule un constructeur. Cette forme permet aux classes et aux types fondamentaux d'être construits à l'aide de la même syntaxe. Elle est donc particulièrement utile lorsque vous définissez des classes de modèles.

Le cast-mot clé est l’un des dynamic_cast, static_cast ou reinterpret_cast. Vous trouverez plus d’informations dans dynamic_cast, static_cast et reinterpet_cast.

L’opérateur typeid est considéré comme une expression postfix. Voir l’opérateur typeid.

Arguments formels et arguments réels

L’appel de programmes transmet des informations à des fonctions appelées dans des « arguments réels ». Les fonctions appelées accèdent aux informations à l’aide des « arguments formels » correspondants.

Lorsqu’une fonction est appelée, les tâches suivantes sont effectuées :

  • Tous les arguments réels (ceux fournis par l'appelant) sont évalués. Il n’y a pas d’ordre implicite dans lequel ces arguments sont évalués, mais ils sont tous évalués et les effets secondaires sont résolus avant l’entrée dans la fonction.

  • Chaque argument formel est initialisé avec son argument réel correspondant dans la liste d'expressions. (Un argument formel est un argument déclaré dans l’en-tête de fonction et utilisé dans le corps d’une fonction.) Les conversions sont effectuées comme si par initialisation : les conversions standard et définies par l’utilisateur sont effectuées pour convertir un argument réel en type correct. L'initialisation exécutée est illustrée conceptuellement par le code suivant :

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

    Les initialisations conceptuelles avant l'appel sont :

    int Temp_i = 7;
    Func( Temp_i );
    

    Notez que l'initialisation est exécutée comme si la syntaxe de signe égal était utilisée au lieu de la syntaxe de parenthèses. Une copie de i est effectuée avant de passer la valeur à la fonction. (Pour plus d’informations, consultez Initialiseurs et conversions).

    Par conséquent, si le prototype de fonction (déclaration) appelle un argument de type longet si le programme appelant fournit un argument de type intréel, l’argument réel est promu à l’aide d’une conversion de type standard en type long (voir Conversions standard).

    C’est une erreur de fournir un argument réel pour lequel il n’existe aucune conversion standard ou définie par l’utilisateur au type de l’argument formel.

    Pour les arguments réels du type classe, l’argument formel est initialisé en appelant le constructeur de la classe. (Voir Constructeurs pour plus d’informations sur ces fonctions membres de classe spéciales.)

  • L'appel de fonction est exécuté.

Le fragment de programme suivant montre un appel de fonction :

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

Lorsqu’il func est appelé à partir du principal, le paramètre param1 formel est initialisé avec la valeur de i (i est converti en type long pour correspondre au type correct à l’aide d’une conversion standard) et le paramètre param2 formel est initialisé avec la valeur de j (j est converti en type double à l’aide d’une conversion standard).

Traitement des types d'arguments

Les arguments formels déclarés en tant que const types ne peuvent pas être modifiés dans le corps d’une fonction. Les fonctions peuvent modifier n’importe quel argument qui n’est pas de type const. Toutefois, la modification est locale dans la fonction et n’affecte pas la valeur de l’argument réel, sauf si l’argument réel était une référence à un objet non de type const.

Les fonctions suivantes illustrent certains de ces concepts :

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

Points de suspension et arguments par défaut

Les fonctions peuvent être déclarées pour accepter moins d’arguments que le nombre spécifié dans la définition de fonction, en utilisant l’une des deux méthodes suivantes : points de suspension (...) ou arguments par défaut.

Les points de suspension indiquent que les arguments peuvent être requis, mais que le nombre et les types ne sont pas spécifiés dans la déclaration. C'est habituellement une mauvaise pratique de programmation C++ car elle occulte l'un des avantages du C++ : la sécurité de type. Différentes conversions sont appliquées aux fonctions déclarées avec des points de suspension que celles pour lesquelles les types d’arguments formels et réels sont connus :

  • Si l’argument réel est de type float, il est promu au type double avant l’appel de fonction.

  • Tout signed char ou, ou unsigned shortunsigned char, signed short type énuméré, ou champ bit est converti en une signed int ou une unsigned int promotion intégrale.

  • Tout argument de type classe est transmis par valeur comme une structure de données. La copie est créée par copie binaire plutôt que par appel d’un constructeur de copie de la classe (le cas échéant).

Les points de suspension, s’ils sont utilisés, doivent être déclarés en dernier dans la liste d’arguments. Pour plus d’informations sur la transmission d’un nombre variable d’arguments, consultez la discussion sur les va_arg, les va_start et les va_list dans la référence de la bibliothèque d’exécution.

Pour plus d’informations sur les arguments par défaut dans la programmation CLR, consultez Listes d’arguments variables (...) (C++/CLI).

Les arguments par défaut vous permettent de spécifier la valeur qu’un argument doit prendre si aucune n’est fournie dans l’appel de fonction. Le fragment de code suivant montre le fonctionnement des arguments par défaut. Pour plus d’informations sur les restrictions relatives à la spécification d’arguments par défaut, consultez Arguments par défaut.

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

Le programme précédent déclare une fonction, print, qui accepte deux arguments. Toutefois, le deuxième argument, terminateur, a une valeur par défaut. "\n" Dans main, les deux premiers appels pour print autoriser le deuxième argument par défaut à fournir une nouvelle ligne pour mettre fin à la chaîne imprimée. Le troisième appel indique une valeur explicite pour le deuxième argument. Le résultat généré par le programme est

hello,
world!
good morning, sunshine.

Voir aussi

Types d’expressions