3

たとえば、C# を考えると

C または C++ の関数ポインターとは異なり、デリゲートはオブジェクト指向であり、タイプ セーフであり、セキュリティで保護されています。

ソース: http://msdn.microsoft.com/en-us/library/aa288459%28v=vs.71%29.aspx

C++ だけについて話しますが、本当の違いは何ですか?また、OO の見込み客に欠けているものは何ですか?

また、別の情報源から

ほとんどの C++ プログラマーはメンバー関数ポインターを使用したことがなく、それには正当な理由があります。それらには独自の奇妙な構文 (たとえば、 ->* および .* 演算子) があり、それらに関する正確な情報を見つけるのは難しく、それらで実行できるほとんどのことは、他の方法でより適切に実行できます。これはちょっとスキャンダラスです: 実際には、コンパイラの作成者にとって、メンバー関数ポインターを実装するよりも、適切なデリゲートを実装する方が簡単です!

ソース: http://www.codeproject.com/Articles/7150/Member-Function-Pointers-and-the-Fastest-Possible

C++ の多くのプログラムがこの->*構文を使用していることがわかりますが、これが奇妙または奇妙であるとは思いません。デリゲートとポインターへの攻撃について、この可能性についての要点がわかりません。

4

3 に答える 3

4

メンバー ポインターと真のクロージャーの違いは、クロージャーには関数関連する状態が含まれていることです。2つは切り離せないものです。

メンバー ポインターは単なる関数です。メンバー ポインターを呼び出すには、状態を指定する必要があります

関数ポインターとファンクターの違いです。関数オブジェクトは、呼び出される関数を ( のオーバーロードとして) 保持しますが、メンバーを持つoperator()こともできます。これらのメンバーは非公開にすることができるため、カプセル化が提供されます。関数オブジェクトは C++ 規則によるオブジェクトであるため、明示的な有効期間があります。C++ の規則に従って構築および破棄されます。

関数ポインターには有効期間がありません。常に存在します (NULL でない限り)。カプセル化する状態はありません。

したがって、何も閉じることができないため、クロージャーではありません。

そのため、C++11 ラムダは明示的なオブジェクトとして実装されています。そうすれば、彼らは物事を閉じることができます。それらはカプセル化された状態を持っています。

于 2012-08-10T20:15:36.867 に答える
3

書くのが難しいと思う人もいると思いますが、通常のポインタのように振る舞います.NULLの場合、実行するのは間違っています. それらが適切に記述され使用されていれば、何も問題はありません。適切な構文を忘れていることを除けば、実際に問題が発生したことはありません。

c++11 では、関数ポインタのラッパーである std::function<> クラスを使用できます。関数、メンバー関数、関数オブジェクト、およびラムダに使用できます。

例えば:

void foo(int x);
std::function<void(int)> f=foo;
f(1);

または簡単(VS2010で動作):

void foo(int x);
std::function<decltype(foo)> f=foo;
f(1);

参照: http://en.cppreference.com/w/cpp/utility/functional/function

于 2012-08-10T20:11:59.457 に答える
0

メンバー関数ポインターはメンバー関数ではありません。C/C++ の関数ポインタは、解放されたメモリを指すか、いつでも NULL に設定される可能性があるという意味で危険です。一般的には回避されますが、boost::bind や印刷関数のスワッピングなどでは常に回避されるわけではありません。

したがって、一般的に、それらは標準のポインターよりも危険ではありません。ただし、多くの場合、オブジェクトのメンバー メソッドまたは静的関数を別の場所で呼び出すだけで、関数ポインターの使用を回避できます。内部で関数ポインターを使用するようにコンパイルされますが、呼び出されたときにその関数の存在がより確実に保証されます。

于 2012-08-10T19:46:59.917 に答える