違いは何ですか
typedef double F(double)
と
typdedef double (*FPT)(double);
?
両方を引数として関数に渡すことができるように思えます。
bar1(FPT f);
bar2(F f);
でもできるうちに
FPT f = &foo;
できない
F f = foo;
つまり、タイプ F の変数を作成できませんか?
違いは何ですか
typedef double F(double)
と
typdedef double (*FPT)(double);
?
両方を引数として関数に渡すことができるように思えます。
bar1(FPT f);
bar2(F f);
でもできるうちに
FPT f = &foo;
できない
F f = foo;
つまり、タイプ F の変数を作成できませんか?
あなたは多くの点で正しいです。F
は関数型でFPT
、関数ポインタ型です。
関数型のオブジェクトがある場合、そのアドレスを取得して関数ポインターを取得できます。ただし、関数型のオブジェクトは、実際のファーストクラスの C++ オブジェクトではありません。実際の関数のみがそのような型であり、(関数を宣言する以外に) 関数であるオブジェクトを作成することはできませんF f = foo;
。
関数を参照できる唯一の方法は、関数ポインターまたは参照を使用することです。
FPT f1 = &foo;
F * f2 = &foo;
F & f3 = foo;
この回答も参照してください。
コールバックの場合、ポインター型よりも参照型を好むことに注意してください。これは、他の変数を渡す方法と比較してより自然であり、参照にアドレスオブと減衰を適用してポインターを取得できるためです。ポインタとは関係ありません:
double callme(F & f, double val) // not: "F *" or "FPT"
{
return f(val);
// "&f" and "std::decay<F>::type" still make sense
}
パラメーター リストでは、関数型は適切な関数ポインター型に減衰します。これにより、同じ型の関数を引数リストのように渡すことができ、それ自体が同じポインター型に減衰します。
これは配列でも同じように機能します。void foo(int arg[4])
には、実際の最初の引数 type がありint *
ます。
8.3.5 関数 [dcl.fct]
5 - [...] 各パラメーターの型を決定した後、「配列
T
」または「関数を返す」型のパラメーターは、それぞれ「へのポインター」または「関数を返すポインターへのポインター」T
になるように調整されます。[...]T
T
宣言での関数型の使用については、同じセクションで説明されています。
10 - 関数型の typedef は、関数を宣言するために使用できますが、関数を定義するために使用してはなりません。