如何定义,分配和使用Pointer-to-Method数组?

时间:2016-08-05 10:09:13

标签: c++ function-pointers member-function-pointers

在我的项目中,我有一个类的层次结构。类型为C_t的对象包含(动态分配的)A_t个对象数组和B_t个对象。

我想从A_t的方法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_t包含AA_tB_t包含BB_t个对象指针。因此,方法调用将如下所示:

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

并给出了长名称:

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

很容易看出这会变得多久而难以阅读。

2 个答案:

答案 0 :(得分:2)

正如托比所指出的那样,你不能用普通的指针来做,但可以用 功能+结合:

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

答案 1 :(得分: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:看起来你的例子中的A_t函数也可以是静态的,这可以解释为什么你没有意识到你需要一个实例。在这种情况下,您可能会考虑简单地使用自由函数而不是将它们放入结构中。 (实际上我不知道如何通过成员函数指针调用静态函数)