2016-08-05 4 views
0

私のプロジェクトでは、私はクラスの階層を持っています。タイプ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 = 46x = 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_tAA_t含まれているとB_tBB_tオブジェクトポインタが含まれています。だから、メソッド呼び出しは次のようになります。

((*p_A)[0]->AA->*(pa_fn[0]))(34); 

と長い名前を与えられた:

((*p_A_object)[0]->AA_sub_object->*(pa_method_fn[0]))(34); 

読み長く、ハードになることができるかを確認することは容易です。トビーが指摘したように

+0

関数ポインタだけでなく、関数の1つを呼び出すには 'A_t'のインスタンスも必要です – user463035818

答えて

2

あなたはプレーンなポインタでそれを行うが、 機能+バインドで可能であることはできません。

std::function<void(int)> f_fn = std::bind(&A_t::a_fn, p_A[0]) ; 
+0

ありがとう。私はこの概念に精通していません。メソッドを呼び出すためにこれをどのように使用しますか? – ysap

+0

ああ、待って...あなたは 'f_fn(46)'をしますか? – ysap

+0

本質的に、これは、同じことをするマクロを定義することに相当する、派手な、C++の同等ですか? – ysap

1

あなたはその機能のいずれかを呼び出すためにA_tとのインスタンスを必要とするこの作品を作るために、関数ポインタだけではありません。例えば。

#include <iostream> 

struct foo { void bar(int x) {std::cout << "moo " << x << std::endl; } }; 

typedef void (foo::*p_fn_t)(int); 

void test(foo f,p_fn_t fn){ (f.*fn)(3); } 

int main() { 
    foo f; 
    p_fn_t fn = &foo::bar; 
    test(f,fn); 
} 

構文が間違っています。メンバ関数ポインタを介して関数を呼び出すのは、.*または->*です。

PS:あなたの例の関数は静的である可能性があります。これは、あなたがインスタンスが必要であることを理解できなかった理由を説明します。その場合は、単に構造体に入れるのではなく、単に空の関数を使うことが考えられます。(実際には、メンバー関数ポインタを介して静的関数を呼び出す方法はわかりません)

+0

[実際の方法は全体がはるかに複雑なので静的ではありません] – ysap

+0

ありがとう。私のプログラムでは、メソッドにアクセスするために 'A_t'のインスタンスを使用します。これは、 '(* p_A)[0]'部分のためのものです。しかし、関数ポインタ自体にオブジェクトの参照を含めることによって、この参照の必要性を排除したいと考えています。だから、おそらく、割り当ては 'pa_fn [0] =&(A [0] - >(A_t :: a_fn))'のテーマに沿ったもののように見えます。 – ysap

+0

質問とサンプルコードが更新されました。 – ysap

関連する問題