1

How do I create an array of method pointers in C++?

The problem is, although these methods have the same signature, they are in different classes. Those classes inherit from one same class.

For example:

class A : public Base {
    virtual bool work();
}

class B : public Base {
    virtual bool work();
}

And I need to create an array of pointers to the methods A::work and B::work, in another class.

Edit 1:

I decided to go with Useless's suggestion, option 1:

vector<Base*> units;
Base *a = new A();
Base *b = new B();
units.push_back(a);
units.push_back(b);

Thanks

user2381422
  • 5,645
  • 14
  • 42
  • 56

4 Answers4

5

First option:

if the different methods are just a implementations of the same virtual method in different subclasses, ie. Base looks like:

class Base {
public:
    virtual bool work() = 0;
}

Then all of your method pointers have type bool (Base::*)(). In this case, your problem is choosing an object to call this method on, so you presumably have a container of Base* pointers with different dynamic types.


Second option:

your classes are really unrelated, and you just want to call some function with signature bool (*)() without worrying about the object.

In this case, either:

  1. your classes and their instances are really irrelevant and you could just use static methods
    • so just use free functions
  2. you need an instance but don't know what type it is when choosing the function

    • you need a functor which can capture the instance, and provide a compatible nullary call operator. As has already been suggested, std::function<bool()> is the simplest way. For example, you could populate a vector like so:

      std::vector<std::function<bool()>> fvec() {
          A a;
          B b;
          std::vector<std::function<bool()>> funcs;
          funcs.push_back( [a]() { return a.work(); } );
          funcs.push_back( [b]() { return b.work(); } );
          return funcs;
      }
      

      Note that the a and b objects are captured by value in the lambdas, so it no longer matters whether A and B have any kind of inheritance relationship.

Useless
  • 64,155
  • 6
  • 88
  • 132
4

create an array (std::vector) of std::function

With std::function you can use std::bind to make a function pointer to any member function. For member functions you have to also bind to a specific instance of the object.

Here is an example of how to use it. std::function to member function

If you do not have c++11 access, you can do the same with boost::bind and boost::function

Community
  • 1
  • 1
Salgar
  • 7,687
  • 1
  • 25
  • 39
2

You can use a combination of std::function and std::bind both of which are found in <functional>.

Example:

#include <functional>
#include <vector>

class Base
{
public:
    virtual bool work() = 0;
};

class A : public Base
{
public:
    bool work() {return true;}
};

class B : public Base
{
public:
    bool work() {return false;}
};

int main()
{
    std::vector<std::function<bool(void)>> list;

    A t1;
    B t2;

    list.push_back(std::bind(&A::work, t1));
    list.push_back(std::bind(&B::work, t2));

    for (auto& i : list)
    {
        printf("%s\n", (i()) ? "true" : "false");
    }
}

Outputs:

true
false
Edward A
  • 2,291
  • 2
  • 18
  • 31
  • Do you think this is better than the approach by Useless above? – user2381422 May 29 '13 at 07:32
  • 1
    @user2381422 As Useless said, they're fairly similar, however I don't see the point of using a lambda that calls the function, it adds levels of indirection, honestly, I find the `bind` option cleaner, this is what I'd use. Also, using `bind` + `function` means you can use all three options, lambdas, pointers, references. – Edward A May 29 '13 at 07:52
1

Well, technically you can create an array of pointers to member functions, although as others suggested, you probably shouldn't. This works:

class Base {
    public:
    bool work()
    {
        return true;
    }
};

int main()
{
    bool (Base::*arr[2])() = { &Base::work, &Base::work };
    return 0;
}