私のプロジェクトでは、私はクラスの階層を持っています。タイプC_t
のオブジェクトは、A_t
オブジェクトとB_t
オブジェクトの(動的に割り当てられた)配列を含みます。Pointer-to-Methodの配列を定義、割り当て、使用する方法は?
メソッドa_fn()
をB_t
のメソッドb_fn()
から呼び出したいとします。私はいくつかのやり方で間接指示を行うことができます。
B
は、そのオブジェクトを含むポインタC
を保持します。次に、私はこのポインタを使って直接A[]
とそのメソッドを参照します。
次に、A_t
へのポインタを定義し、A[]
への参照でそれらを初期化し、これらのポインタを使って間接的にA[]
のメソッドを呼び出します。
実際のプロジェクトでは、階層が深く、オブジェクト名が説明的で長く、このスタイルは長く畳み込まれたステートメントになるとします。
A[]
のメソッドa_fn()
へのポインタ配列を維持し、これらの配列メンバーを使用してメソッドを呼び出す必要があります。つまり、x = 46
とx = 47
を印刷する(コメントアウト)ステートメントを作成する方法は?
#include <iostream>
using namespace std;
struct A_t;
struct B_t;
struct C_t;
// Top level class
struct C_t {
A_t *A[2];
B_t *B;
C_t();
};
struct A_t {
void a_fn(int x) { cout << "x = " << x << endl; };
};
// Define func-ptr to A_t's method
typedef void (A_t::*p_fn_t)(int);
struct B_t {
C_t* p_C; // ptr to containing object
A_t** p_A[2]; // array of ptrs-to-array-of-As
p_fn_t p_fn; // ptr to A_t's method
p_fn_t pa_fn[2]; // array of ptr to A_t's method
void b_fn() {
p_C->A[0]->a_fn(10); // Cptr-direct
(p_C->A[0]->*p_fn)(11); // Cptr-indirect
(*p_A)[1]->a_fn(22); // Aptr-direct
((*p_A)[1]->*p_fn)(23); // Aptr-indirect
((*p_A)[0]->*(pa_fn[0]))(34); // Aptr-fptr-indirect
((*p_A)[1]->*(pa_fn[1]))(35); // Aptr-fptr-indirect
//pa_fn[0](46); // <<-- HOW TO DO THIS???
//pa_fn[1](47); // <<-- HOW TO DO THIS???
};
B_t(C_t *C) : p_C(C) {
p_fn = &A_t::a_fn; // init fptr-to-A's-method
p_A[0] = &(p_C->A[0]); // init ptr-to-A[0]
p_A[1] = &(p_C->A[1]); // init ptr-to-A[1]
// The following assignments need to change in order to get
// what I am looking for. Something along the line of
// pa_fn[0] = &(A[0]->(A_t::a_fn));
pa_fn[0] = &A_t::a_fn; // init fptr-to-A's-method
pa_fn[1] = &A_t::a_fn; // init fptr-to-A's-method
};
};
C_t::C_t() {
// Instantiate As and B and init B with C's own ptr
A[0] = new A_t;
A[1] = new A_t;
B = new B_t(this);
};
int main(int argc, char *argv[])
{
C_t C;
C.B->b_fn(); // Invoke B's method
return 0;
}
このプログラムの出力:
x = 10
x = 11
x = 22
x = 23
x = 34
x = 35
更新:実際のプロジェクトで階層の別のレベルがありますが、そうA_t
はAA_t
含まれているとB_t
はBB_t
オブジェクトポインタが含まれています。だから、メソッド呼び出しは次のようになります。
((*p_A)[0]->AA->*(pa_fn[0]))(34);
と長い名前を与えられた:
((*p_A_object)[0]->AA_sub_object->*(pa_method_fn[0]))(34);
読み長く、ハードになることができるかを確認することは容易です。トビーが指摘したように
関数ポインタだけでなく、関数の1つを呼び出すには 'A_t'のインスタンスも必要です – user463035818