[解決済み] フリー関数が期待されるメンバ関数を渡すにはどうしたらよいですか?
質問
次のような問題です:このコードの一部を考えてみてください。
#include <iostream>
class aClass
{
public:
void aTest(int a, int b)
{
printf("%d + %d = %d", a, b, a + b);
}
};
void function1(void (*function)(int, int))
{
function(1, 1);
}
void test(int a,int b)
{
printf("%d - %d = %d", a , b , a - b);
}
int main()
{
aClass a;
function1(&test);
function1(&aClass::aTest); // <-- How should I point to a's aClass::test function?
}
を使用するにはどうすればよいですか?
a
's
aClass::test
を引数として
function1
? クラスのメンバにアクセスしたいのですが。
どのように解決するのですか?
関数ポインタを使うことは悪いことではありません。しかし、非静的メンバ関数へのポインタは、通常の関数ポインタとは異なります。メンバ関数は、関数への暗黙の引数として渡されるオブジェクト上で呼び出される必要があります。上のメンバ関数のシグネチャは、次のようになります。
void (aClass::*)(int, int)
を使おうとするタイプではなく
void (*)(int, int)
一つのアプローチとして、メンバー関数
static
この場合、呼び出されるオブジェクトは必要なく、このオブジェクトを
void (*)(int, int)
.
クラスの非静的メンバにアクセスする必要がある場合
と
関数がC言語のインターフェイスの一部である場合など、 関数ポインタにこだわる必要がある場合は、常に
void*
からオブジェクトを取得する転送関数を通してメンバを呼び出します。
void*
を作成し、メンバー関数を呼び出す。
適切な C++ インタフェースでは、関数オブジェクトが任意のクラス型を使用できるように、関数がテンプレート化された引数を取るようにすることを検討するとよいでしょう。もし、テンプレート化されたインタフェースを使うのが望ましくないのであれば、次のようなものを使うべきです。
std::function<void(int, int)>
: これらに対して、適切に呼び出し可能な関数オブジェクトを作成することができます。
std::bind()
.
タイプセーフのアプローチでは、クラスの型に対するテンプレート引数や、適切な
std::function<...>
を使うよりも
void*
インターフェイスを使用すると、間違った型へのキャストによるエラーの可能性がなくなるからです。
関数ポインタを使用してメンバ関数を呼び出す方法を明確にするために、以下に例を示します。
// the function using the function pointers:
void somefunction(void (*fptr)(void*, int, int), void* context) {
fptr(context, 17, 42);
}
void non_member(void*, int i0, int i1) {
std::cout << "I don't need any context! i0=" << i0 << " i1=" << i1 << "\n";
}
struct foo {
void member(int i0, int i1) {
std::cout << "member function: this=" << this << " i0=" << i0 << " i1=" << i1 << "\n";
}
};
void forwarder(void* context, int i0, int i1) {
static_cast<foo*>(context)->member(i0, i1);
}
int main() {
somefunction(&non_member, nullptr);
foo object;
somefunction(&forwarder, &object);
}
関連
-
[解決済み】ファイルから整数を読み込んで配列に格納する C++ 【クローズド
-
[解決済み】std::cin.getline( ) vs. std::cin
-
[解決済み] 変数を参照渡しする方法を教えてください。
-
[解決済み] Node.jsのプログラムにコマンドライン引数を渡すにはどうしたらいいですか?
-
[解決済み] Linux上で動作するC++コードのプロファイリングを行うにはどうすればよいですか?
-
[解決済み] バッチファイルに引数を渡すにはどうしたらいいですか?
-
[解決済み] PowerShellで関数に複数のパラメータを渡すにはどうすればよいですか?
-
[解決済み] コンストラクタや関数に unique_ptr 引数を渡すにはどうしたらいいですか?
-
[解決済み】C言語の関数ポインタはどのように機能するのですか?
-
[解決済み】派生クラスでオーバーライドされた関数が、ベースクラスの他のオーバーロードを隠してしまうのはなぜですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】C++エラー。アーキテクチャ x86_64 に対して未定義のシンボル
-
[解決済み】LLVMで暗黙のうちに削除されたコピーコンストラクタの呼び出し
-
[解決済み】C-stringを使用すると警告が表示される。"ローカル変数に関連するスタックメモリのアドレスが返される"
-
[解決済み】C++でユーザー入力を待つ【重複あり
-
[解決済み】変数 '' を抽象型 '' と宣言できない。
-
[解決済み】デバッグアサーションに失敗しました。C++のベクトル添え字が範囲外
-
[解決済み】クラステンプレートの使用にはテンプレート引数リストが必要です
-
[解決済み】VC++の致命的なエラーLNK1168:書き込みのためにfilename.exeを開くことができません。
-
[解決済み】システムが指定されたファイルを見つけられませんでした。
-
[解決済み] std::function vs テンプレート