関数の名前(たとえばA)を引数として別の関数(たとえばB)に渡し、関数Bから関数Aを呼び出すことは可能ですか?つまり、関数名はBの変数に格納され、名前が変数にある関数を呼び出します。たとえば、C ++の並べ替え関数では、最初と2番目の引数はイテレータですが、3番目の引数は関数の名前です。
5 に答える
Pred
「2 つのパラメーターで呼び出し可能なもの」のテンプレート パラメーター (こちら) を導入できます。
template <typename Iter, typename Pred>
void mysort(Iter begin, Iter end, Pred predicate)
{
--end;
// ...
if (predicate(*begin, *end))
{
// ...
}
// ...
}
次に、古き良き C 関数ポインターまたは C++ 関数オブジェクトのいずれかを渡すことができます。
bool function(int x, int y)
{
return x < y;
}
struct function_object
{
bool operator()(int x, int y)
{
return x < y;
}
};
int main()
{
int numbers[] = {543, 6542654, 432514, 54, 45, 243};
mysort(numbers + 0, numbers + 6, &function);
mysort(numbers + 0, numbers + 6, function_object());
}
ご覧のとおり、関数オブジェクトは、operator()
適切にオーバーロードするクラスのオブジェクトです。
関数ポインタを読む必要があります。
関数ポインターを使用した簡単な例:
#include <iostream>
int apply(int (*fun)(int,int), int a, int b) {
return (*fun)(a,b);
}
int add(int a, int b) {return a + b;}
int multiply(int a, int b) {return a * b;}
int main(int argc, const char* argv[]) {
int added = apply(add, 2, 4);
int multiplied = apply(multiply, 2, 4);
std::cout << "added result: " << added << std::endl;
std::cout << "multiplied result: " << multiplied << std::endl;
}
出力:
added result: 6
multiplied result: 8
はい、可能であるだけでなく、優れた使用法もあります。
技術的には、これらは関数ポインタとして知られています。
概念的には、コールバックメカニズムが必要です。イベント ドリブンプログラムでは、コールバックが必要になる場合があります。例えば、あなたのアプリケーションは、マウスボタンがクリックされたときを知ることに関心があるかもしれません。この場合、マウス クリック イベントの基礎となるプラットフォームに関心を登録し、プログラムでどのメソッド/関数を呼び出す必要があるかを通知して、それに応じてコードを実行できるようにします。
別のそのようなケースは、プログラムが非同期モードで実行される場合です。たとえば、ファイルがハードディスクに書き込まれる場合、これは算術計算を行うのに比べて時間がかかるプロセスです。そのため、結果をファイルに書き込んでいる間、計算の実行を待ちたくない場合があるかもしれません。プログラムは、ファイルに対して書き込み関数を呼び出し、戻り、計算を開始することを選択する場合があります。一方、この関数を呼び出すと、呼び出し元はコールバック関数を指定することもあります。そのため、ファイルの書き込みが成功または失敗すると、コールバック関数が呼び出され、呼び出し先に通知されます。
はい、可能です。技術的には、渡されるのは「名前」ではなく、実際には渡される関数へのポインタです。