0

In my project I have an hierarchy of classes. An object of type C_t contains (dynamically allocated) array of A_t objects and a B_t object.

I want to invoke an A_t method a_fn() from a B_t's method b_fn(). I can do that in several ways, and several levels of indirection.

B maintains a pointer to its containing object C. Then I use this pointer to directly refer to A[] and its method.

Next, I defined pointers to A_t and initialized them with the references to A[]s, and use these pointers to indirectly invoke A[]'s method.

Assume that in the actual project the hierarchy is deeper and that the object names are descriptive and long, this style becomes long and convoluted statements.

I want to maintain an array of pointers to A[]'s method a_fn() and use these array members to invoke the methods. I.e., how to make the (commented out) statements that would print x = 46 and x = 47 work?

#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;
}

This program's output:

x = 10
x = 11
x = 22
x = 23
x = 34
x = 35

Update: In the actual project there is another level of hierarchy, so A_t contains AA_t and B_t contains BB_t object pointers. So, the method invocation will look like:

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

and given long names:

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

It is easy to see how this can become long and hard to read.

1
  • you need also an instance of A_t to call one of its functions, not only a function pointer Commented Aug 5, 2016 at 10:29

2 Answers 2

2

As Toby pointed out you can't do it with plain pointers, but is possible with function+bind:

std::function<void(int)> f_fn = std::bind(&A_t::a_fn, p_A[0]) ;
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks. I am not familiar with the concept. How do you use this to invoke the method?
Oh, wait... you will do f_fn(46)?
Essentially, this is the fancy, C++ equivalent to defining a macro that does the same thing?
1

To make this work you need an instance of A_t to call one of its functions, not only a function pointer. E.g. like this:

#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);
}

The syntax is easy to get wrong. It is .* or ->* to invoke a function via a member function pointer.

PS: it seems like A_ts function in your example could be as well static, which would explain why you didnt realize that you need an instance. In that case you might consider to simply use free functions instead of putting them into a struct. (Actually I dont know how to invoke a static function via a member function pointer)

7 Comments

[The actual method is not static as the whole thing is much more complicated]
Thanks. In my program I use an instance of A_t to access the method. This is what the (*p_A)[0] part is for. But I want to eliminate the need for this reference by including the object's reference in the function pointer itself. So, supposedly, the assignment will look like something along the theme of pa_fn[0] = &(A[0]->(A_t::a_fn)).
@ysap thats actually a different question and I think you can get it working with std::function and std::bind to bind the instance parameter
Basically, what @marom suggests. (I don't see why it is a different question, though)
@ysap because "how can I bind an instance to a member function pointer?" is a different question than "how can I use an array of member function pointers?"
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.