views:

104

answers:

3

I have a class A which contains member functions foo() and bar() which both return a pointer to class B. How can I declare an array containing the functions foo and bar as a member variable in class A? And how do I call the functions through the array?

+8  A: 

The member function pointer syntax is ReturnType (Class::*)(ParameterTypes...), so e.g.:

typedef B* (A::*MemFuncPtr)(); // readability
MemFuncPtr mfs[] = { &A::foo, &A::bar }; // declaring and initializing the array
B* bptr1 = (pointerToA->*mfs[0])(); // call A::foo() through pointer to A
B* bptr2 = (instanceOfA.*mfs[0])(); // call A::foo() through instance of A

See e.g. this InformIT article for more details on pointers to members.

You might also want to look into Boost.Bind and Boost.Function (or their TR1 equivalents) which allow you to opaquely bind the member-function-pointers to an instance:

typedef boost::function<B* ()> BoundMemFunc;
A instanceOfA;
BoundMemFunc mfs[] = { 
    boost::bind(&A::foo, &instanceOfA), 
    boost::bind(&A::bar, &instanceOfA) 
};
B* bptr = mfs[0](); // call A::foo() on instanceOfA

To use such an array as a member, note that you can't initialize arrays using the member initializer list. Thus you can either assign to it in the constructor body:

A::A {
    mfs[0] = &A::foo;
}

... or you use a type that can actually be initialized there like std::vector or boost::array:

struct A {
    const std::vector<MemFuncPtr> mfs;
    // ...
};

namespace {
    std::vector<MemFuncPtr> init_mfs() {
        std::vector<MemFuncPtr> mfs;
        mfs.push_back(&A::foo);
        mfs.push_back(&A::bar);
        return mfs;
    }
}

A::A() : mfs(init_mfs()) {}
Georg Fritzsche
You could also consider good use of std::function.
DeadMG
@DeadMG: I mentioned the TR1 version but went for the Boost version as it has the broadest availability. I personally consider the C++0x versions as not widespread enough and the new standard is also not finalized yet.
Georg Fritzsche
Ah, so you did. Since I got a C++0x compiler myself, I'm not used to seeing the boost variants.
DeadMG
A: 

The best idea here is to proceed step by step.

First, the declaration for your functions foo and bar is

B* foo()

Next, a pointer pFoo to such a function is declared as

B* (*pFoo)()

The best idea is to then define a type using typedef

typedef B* (*pointer_to_foos)();

Then you can just use pointer_to_foos in your array declaration, e.g.

pointer_to_foos pointerArray[42] = {......}
pointer_to_foos* dyn_array = (pointer_to_foos*) malloc(......)

PS: A quick google search for "array of function pointers" would have answered your question just as quickly.

PPS: Consider using inheritance and abstract classes instead of function pointers if it seems appropriate.

Lagerbaer
-1: The OP is talking about pointers to member functions, *not* about pointers to ordinary functions.
Job
-1: wtfmalloc, just why?
DeadMG
he's a c/c++ programmer!
Matt Joiner
+2  A: 

What you're looking for are pointers to member functions. Here is a short sample that shows their declaration and use:

#include <iostream>

class B {
public:
  B(int foo): foo_(foo) {
    std::cout << "Making a B with foo_ = " << foo_ << std::endl;
  }
  ~B(void) {
    std::cout << "Deleting a B with foo_ = " << foo_ << std::endl;
  }
  int foo_;
};

class A {
public:
  A(void) {
    funcs_[0] = &A::foo;
    funcs_[1] = &A::bar;
  }

  B* foo(void) {
    return new B(3);
  }

  B* bar(void) {
    return new B(5);
  }

  // Typedef for the member function pointer, for everyone's sanity.
  typedef B* (A::*BMemFun)(void);
  BMemFun funcs_[2];
};

int main(int argc, char *argv[]) {
  A a;
  for (int i = 0; i < 2; ++i) {
    A::BMemFun func = a.funcs_[i];
    // Call through the member function pointer (the .* operator).
    B* b = (a.*func)();
    delete b;
  }
  return 0;
}

The C++ FAQ section on pointers to member functions is where I found all this information.

Jack Kelly