Freigeben über


Postfixausdrücke

Postfixausdrücke bestehen aus primären Ausdrücken bzw. Ausdrücken, in denen Postfixoperatoren einem primären Ausdruck folgen. Die Postfix-Operatoren sind in der folgenden Tabelle aufgeführt.

Postfix-Operatoren

Name des Operators Operator-Notation
Subscript-Operator [ ]
Funktionsaufrufoperator ( )
Operator für die explizite Typkonvertierung type-name ( )
Memberzugriffsoperator . oder ->
Postfix-Operator für Inkrement ++
Postfix-Operator für Dekrement --

Die folgende Syntax beschreibt mögliche Postfixausdrücke:

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 )

Der oben angegebene postfix-expression kann ein primärer oder ein anderer Postfixausdruck sein. Postfixausdrücke gruppieren sich von links nach rechts und ermöglichen so das Verketten der Ausdrücke wie folgt:

func(1)->GetValue()++

Im obigen Ausdruck ist func ein primärer Ausdruck, func(1) ist ein Funktions-Postfixausdruck, func(1)->GetValue ist ein Postfixausdruck, der einen Member der Klasse angibt, func(1)->GetValue() ist ein weiterer Funktions-Postfixausdruck, und der gesamte Ausdruck ist ein Postfixausdruck, der den Rückgabewert von GetValue erhöht. Die Bedeutung des Ausdrucks als Ganzes ist „Funktion aufrufen, dabei 1 als Argument übergeben und einen Zeiger für eine Klasse als Rückgabewert erhalten. Dann GetValue() für diese Klasse aufrufen und den zurückgegebenen Wert erhöhen.

Die oben aufgeführten Ausdrücke sind Zuweisungsausdrücke, was bedeutet, dass das Ergebnis dieser Ausdrücke ein "r-value" sein muss.

Die Form des Postfixausdrucks

simple-type-name ( expression-list )

gibt den Aufruf des Konstruktors an. Wenn "simple-type-name" ein grundlegender Typ ist, muss die Ausdrucksliste ein einzelner Ausdruck sein, und dieser Ausdruck gibt eine Umwandlung des Werts des Ausdrucks in den einfachen Typ an. Dieser Typ von Umwandlungsausdruck imitiert einen Konstruktor. Da diese Form die Konstruktion grundlegender Klassen und Typen mit derselben Syntax ermöglicht, ist sie bei der Definition von Vorlagenklassen besonders nützlich.

Das cast-keyword ist eines von dynamic_cast, static_cast oder reinterpret_cast. Weitere Informationen finden Sie in dynamic_cast, static_cast und reinterpet_cast.

Der typeid-Operator gilt als Postfixausdruck. Weitere Informationen erhalten Sie unter typeid-Operator.

Formale und tatsächliche Argumente

Aufrufende Programme übergeben Informationen an die aufgerufenen Funktionen in „tatsächlichen Argumenten“. Die aufgerufenen Funktionen greifen mithilfe der entsprechenden „formalen Argumente“ auf die Informationen zu.

Wenn eine Funktion aufgerufen wird, werden die folgenden Aufgaben ausgeführt:

  • Alle tatsächlichen Argumente (die vom Aufrufer angegebenen) werden ausgewertet. Es gibt keine implizite Reihenfolge, in der diese Argumente ausgewertet werden. Alle Argumente werden jedoch ausgewertet, und alle Nebeneffekte werden vor dem Eintritt in die Funktion abgeschlossen.

  • Jedes formale Argument wird mit dem entsprechenden tatsächlichen Argument in der Ausdrucksliste initialisiert. (Ein formales Argument ist ein Argument, das im Funktionsheader deklariert und im Text einer Funktion verwendet wird.) Konvertierungen werden wie durch Initialisierung ausgeführt. Sowohl Standard- als auch benutzerdefinierte Konvertierungen werden beim Konvertieren eines tatsächlichen Arguments in den richtigen Typ ausgeführt. Die ausgeführte Initialisierung wird durch den folgenden Code konzeptionell veranschaulicht:

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

    Die konzeptionellen Initialisierungen vor dem Aufruf sind:

    int Temp_i = 7;
    Func( Temp_i );
    

    Beachten Sie, dass die Initialisierung ausgeführt wird, als würde die Gleichheitszeichensyntax anstelle der Klammersyntax verwendet werden. Eine Kopie von i wird vor dem Übergeben des Werts an die Funktion erstellt. (Weitere Informationen finden Sie unter Initialisierer und Konvertierungen).

    Wenn der Funktionsprototyp (Deklaration) daher ein Argument des Typs long aufruft und wenn das aufrufende Programm ein tatsächliches Argument des Typs int bereitstellt, wird das tatsächliche Argument mit einer Standardkonvertierung auf den Typ long erweitert (siehe Standardkonvertierungen).

    Es ist ein Fehler, ein tatsächliches Argument anzugeben, für das es keine Standard- oder benutzerdefinierte Konvertierung in den Typ des formalen Arguments gibt.

    Für die tatsächlichen Argumente des Klassentyps wird das formale Argument initialisiert, indem der Konstruktor der Klasse aufgerufen wird. (Weitere Informationen über diese speziellen Klassenmemberfunktionen finden Sie unter Konstruktoren.)

  • Der Funktionsaufruf wird ausgeführt.

Das folgende Programmfragment zeigt einen Funktionsaufruf:

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

Wenn func aus Main aufgerufen wird, wird der formale Parameter param1 mit dem Wert von i initialisiert (i wird mithilfe einer Standardkonvertierung in den Typ long konvertiert, damit es dem richtigen Typ entspricht), und der formale Parameter param2 wird mit dem Wert von j initialisiert (j wird mit einer Standardkonvertierung in den Typ double konvertiert).

Behandlung von Argumenttypen

Formale Argumente, die als const-Typen deklariert sind, können im Funktionstext nicht geändert werden. Funktionen können jedes Argument ändern, das nicht vom Typ const ist. Allerdings ist die Änderung auf die Funktion beschränkt und wirkt sich nicht auf den Wert des tatsächlichen Arguments aus, es sei denn, das tatsächliche Argument ist ein Verweis auf ein Objekt, das nicht den Typ const aufweist.

Die folgenden Funktionen veranschaulichen einige dieser Konzepte:

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

Auslassungspunkte und Standardargumente

Funktionen können deklariert werden, um weniger Argumente als in der Funktionsdefinition angegeben mit einer der folgenden beiden Methoden zu akzeptieren: Auslassungspunkte (...) oder Standardargumente.

Auslassungspunkte geben an, dass Argumente möglicherweise erforderlich sind, dass die Anzahl und Typen jedoch nicht in der Deklaration angegeben werden. Dies ist normalerweise ein schlechtes Beispiel für C++-Programmierung, da es einen der Vorteile von C++ unterlaufen kann: Typsicherheit. Verschiedene Konvertierungen werden auf Funktionen angewendet, die mit Auslassungszeichen deklariert sind, und nicht auf jene Funktionen, deren formale und tatsächliche Argumenttypen bekannt sind:

  • Wenn das tatsächliche Argument vom Typ float ist, wird es vor dem Funktionsaufruf auf den Typ double hochgestuft.

  • Ein beliebiges signed char oder unsigned char, signed short oder unsigned short, aufgezählter Typ oder Bitfeld wird mithilfe von verwendungsintegrierter Heraufstufung entweder in eine signed int oder eine unsigned int konvertiert.

  • Jedes Argument des Klassentyps wird durch einen Wert als Datenstruktur übergeben; die Kopie wird durch Kopieren der Binärdatei statt durch Aufrufen des Kopierkonstruktors der Klasse erstellt (falls vorhanden).

Auslassungspunkte müssen in der Argumentliste zuletzt deklariert werden, sofern sie vorhanden sind. Weitere Informationen zum Übergeben einer variablen Anzahl von Argumenten finden Sie in den Ausführungen zu va_arg, va_start und va_list in der Laufzeitbibliotheksreferenz.

Informationen zu Standardargumenten in der CLR-Programmierung finden Sie unter Variablenargumentlisten (...) (C++/CLI).

Mit Standardargumenten können Sie den Wert festlegen, den ein Argument annehmen soll, wenn keiner im Funktionsaufruf angegeben wird. Das folgende Codefragment zeigt, wie Standardargumente funktionieren. Weitere Informationen zu Einschränkungen beim Festlegen von Standardargumenten, finden Sie unter Standardargumente.

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

Das vorangehende Programm deklariert eine Funktion, print, die zwei Argumente akzeptiert. Das zweite Argument, Terminator, weist jedoch einen Standardwert "\n" auf. In main ermöglichen die ersten beiden Aufrufe von print dem zweiten Standardargument die Bereitstellung einer neuen Zeile, um die gedruckte Zeichenfolge zu beenden. Der dritte Aufruf gibt einen expliziten Wert für das zweite Argument zurück. Die Ausgabe des Programms lautet

hello,
world!
good morning, sunshine.

Weitere Informationen

Ausdruckstypen