後置式

後置式は、1 次式、または後置演算子が 1 次式に続く式で構成されます。 次の表は、後置演算子の一覧です。

後置演算子

演算子名 演算子表記
添字演算子 [ ]
関数呼び出し演算子 ( )
明示的な型変換演算子 type-name( )
メンバー アクセス演算子 . または -
後置インクリメント演算子 ++
後置デクリメント演算子 --

次の構文は、可能な後置式について説明しています。

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()++

上の式では、 はプライマリ式、 は関数の後置式、 は クラスのメンバーを指定する後置式、もう 1 つの関数の後置式、式全体は funcfunc(1)func(1)->GetValuefunc(1)->GetValue() GetValue の戻り値をインクリメントする後置式です。 全体として式の意味は、「引数として 1 を渡す関数を呼び出し、戻り値としてクラスへのポインターを取得します。 次に、 GetValue() そのクラスで を呼び出し、返された値をインクリメントします。

前の式は、代入式です。つまり、これらの式の結果が右辺値である必要があります。

後置式のフォーム

simple-type-name ( expression-list )

コンストラクターの呼び出しを示します。 単純型名が基本型である場合、式リストは 1 つの式である必要があります。また、この式は、基本型への式の値のキャストを示します。 この型のキャスト式はコンストラクターを模倣します。 この形式は同じ構文を使用して構築されている基本型とクラスを使用するため、この形式はテンプレート クラスを定義する場合に特に便利です。

cast-keyword は、、、または の 1 static_cast つです reinterpret_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 のコピーは、関数に値を渡す前に作成されます (詳細については、「初期化子と変換」を参照してください

    したがって、関数プロトタイプ (宣言) が 型の引数を呼び出し、呼び出し元のプログラムが 型の実際の引数を指定する場合、実際の引数は標準の型から 型への変換を使用して昇格されます longintlong (「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 )
{
}

が main から呼び出されると、仮パラメーターは の値で初期化され ( は標準変換を使用して正しい型に対応するために型に変換されます)、仮パラメーターは の値で初期化されます funcparam1iilongparam2j ( jdouble は標準変換を使用して型に変換されます)。

引数の型の処理

型として宣言された仮引数 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++ の利点の 1 つであるタイプ セーフが活用できないため、C++ のプログラミングとしてお勧めできません。 省略記号で宣言された関数には、仮引数型と実際の引数型が知られている関数とは異なる変換が適用されます。

  • 実際の引数が 型の場合 float 、関数呼び出しの前に 型 double に昇格されます。

  • または signed charunsigned char または signed short 、列挙型、またはビット フィールドは、整数の昇格を使用して、 または unsigned shortsigned intunsigned 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;
}

上のプログラムでは 2 個の引数を受け取る関数、print を宣言します。 ただし、2 番目の引数 ターミネータには既定値 があります 。 では、最初の 2 つの 呼び出しで、既定の 2 番目の引数が新しい行を指定して、印刷 mainprint された文字列を終了できます。 3 番目の呼び出しでは、2 番目の引数の明示的な値が指定されます。 このプログラムによる出力は次のとおりです。

hello,
world!
good morning, sunshine.

こちらもご覧ください

式の種類