Help with an array of member function pointers in a class

I'm trying to implement an array of member function pointers in a class. I've googled around, and this is what I've come up with. Its not working and giving me all sorts of errors.

How would I do this?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
 #include <stdio.h>
#include<iostream>

using namespace std;


class MyClass{
public:
    static const int SCREAM = 0,WHISPER = 1,SLEEP = 2;
    void emote();

private:
    typedef void(MyClass::*reaction)();
    reaction react[3]= {&MyClass::scream,&MyClass::whisper,&MyClass::sleep};
    void scream();
    void whisper();
    void sleep();

};

void MyClass::scream(){
    cout << "eeeeek"<< endl;
}
void MyClass::whisper(){
    cout << "ssshhhhhhh"<< endl;
}
void MyClass::sleep(){
    cout << "zzzzZZZZZ"<< endl;
}
void MyClass::emote(){
    react[SCREAM]();
    react[WHISPER]();
    react[SLEEP]();
}
int main()
{
   MyClass c;
   c.emote();
}
Last edited on
A non-static member function pointer can't be called in the usual way. You've got to tell it which object to use.
In particular, the left of the function-call operator has to be a pending member-function invocation - a special kind of expression using the operators .* or ->* like this:
1
2
3
4
5
6
7
8
void MyClass::emote(){
    (this->*react[SCREAM])();
    (this->*react[WHISPER])();

    // or through an object:
    MyClass& x = *this;
    (x.*react[SLEEP])();
}


In your particular case, you might as well make your functions static, in which case you can treat them just like normal function pointers:
1
2
3
4
5
6
7
typedef void(*reaction)();
reaction react[3]= {&MyClass::scream,&MyClass::whisper,&MyClass::sleep};
static void scream();
// ...
react[SCREAM]();
react[WHISPER]();
react[SLEEP]();


If this is not possible and your functions must be non-static, you can (and usually should) use std::function to homogenize:
1
2
3
4
5
std::function<void(MyClass*)> react[3] = {&MyClass::scream,&MyClass::whisper,&MyClass::sleep};
// ... 
react[SCREAM](this);
react[WHISPER](this);
react[SLEEP](this);


Last edited on
That worked. Thanks for the help.
How would I use
1
2
3
4
5
std::function<void(MyClass*)> react[3] = {&MyClass::scream,&MyClass::whisper,&MyClass::sleep};
// ... 
react[SCREAM](this);
react[WHISPER](this);
react[SLEEP](this);


If the functions had paremeters? e.g.,

1
2
3
void MyClass::scream(string s){
      cout <<  s<< endl;
}


or if it returned a value?

1
2
3
4
5
bool MyClass::scream(string s){
      bool screamed = true;
      cout <<  s<< endl;
      return screamed;
}


Edit: I found it. For a function that returns void and takes a string for a parameter it would be:

std::function<void(MyClass*,string) > react[3]={&MyClass::scream,&MyClass::whisper,&MyClass::sleep};

if it returned something like a boolean it would be:

std::function<bool(MyClass*,string) > react[3]={&MyClass::scream,&MyClass::whisper,&MyClass::sleep};
Last edited on
You place the type of the function to be called (note: not the type of the pointer-to-function) in the angle brackets. In other words, you write std::function< return_type(parameter_type_1, parameter_type_2, ..., parameter_type_n) >
For instance, to create a std::function that targets the function f():
 
int f(char a, double b);

Which returns int and accepts two parameters of types char and double:
 
std::function< int(char, double) > g = f;


If the function being targeted is a member function, the std::function needs to take a pointer or reference (or some other related things) to the object as its first parameter. This is because member functions take a pointer to the object to be called as the first argument, called the implicit object argument. So given bool MyClass::scream(string s), the associated function object needs to have the type
1
2
std::function< bool(MyClass*, string) > f = &MyClass::scream; // or
std::function< bool(MyClass&, string) > g = &MyClass::scream;

To be called like
1
2
3
A a; 
f(&a, "my string"); // or
g(a, "my_string");

Last edited on
Thank you for the explanation. The static method worked fine, but when I started using it in my real program I was running into problems with static functions calling non-static functions.

This way works fine. I really appreciate the help.

I working on porting a paint program I wrote in java, to Qt in C++. Ill post a link to github when I get a little further along. Each of those emotes above are really different types of drawing tools in my real program.
Last edited on
I working on porting a paint program I wrote in java, to Qt in C++. Ill post a link to github when I get a little further along.

Neat. Looking forward to seeing the results.
Here is the beginning of it. As I said, its written in Qt (https://www.qt.io/) so one would need that development environment to compile it.

https://github.com/shawnlau/QtPaintProgram/tree/master/QtPaintProgram

Your help is in the mycanvas.h. Right now there are only two mouse functions - draw ( not implemented yet) and drag.

So far I know there's a huge memory leak in the MyCanvas::paintEvent override. But I can't figure it out. I'm deleting the only new object at the end of the function.
Last edited on
Topic archived. No new replies allowed.