Using function pointers on class member functions

Hello,

I am trying to do the following:

- Have a chooser function which returns a function pointer
- Then based on this pointer I run the corresponding function

Then I try to implement the same, but with the collection of functions enclosed in a class - this is the problem

The original code (which works fine):
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
#include <iostream>
#include <algorithm>

using namespace std;

typedef void (*ptr_to_chosen_func) ();
ptr_to_chosen_func choose_func(int);
    void func_1()     {cout << "breed unicorns" << endl;}
    void func_2()      {cout << "destroy planets" << endl;}

int main()
{
ptr_to_chosen_func b;
b = choose_func(2);
b();

    return 0;
}

ptr_to_chosen_func choose_func(int a){
    ptr_to_chosen_func b;
     if (a == 1 ) {b = func_1;}
     if (a != 1 ) {b = func_2;}
return b;
}


This is how I am trying to do it with class function pointers:

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
#include <iostream>
#include <algorithm>

using namespace std;

struct collection_of_funcs {
    typedef void (collection_of_funcs::*ptr_to_chosen_func) ();
    ptr_to_chosen_func choose_func(int);
        void func_1()     {cout << "breed unicorns" << endl;}
        void func_2()      {cout << "destroy planets" << endl;}
};

int main()
{
// void (collection_of_funcs::*ptr_to_chosen_func) ();
collection_of_funcs *ptr = NULL;
ptr = new collection_of_funcs;
ptr_to_chosen_func b = choose_func(1);
     (ptr->*b)();
    delete ptr;
    return 0;
}

ptr_to_chosen_func collection_of_funcs::choose_func(int a){
    ptr_to_chosen_func b;
     if (a == 1 ) {b = collection_of_funcs::func_1;}
     if (a != 1 ) {b = collection_of_funcs::func_2;}
return b;
}


The errors I get are:
1
2
3
4
|18|error: invalid use of 'collection_of_funcs::ptr_to_chosen_func'|
|19|error: 'b' was not declared in this scope|
|19|error: 'choose_func' was not declared in this scope|
|25|error: 'ptr_to_chosen_func' does not name a type|


the issue seems to be with declaration of the typedefs and accessing the pointer within the class
Hi,

You could try using std::function, look at the example here:
http://en.cppreference.com/w/cpp/utility/functional/function

Also a std::vector of std::function, then you won't have to use new / delete, and you could use the vector subscript to help call the selected function.
https://stackoverflow.com/questions/1112584/stdvector-of-functions

Also use nullptr instead of NULL
The address of a member-function pointer must be obtained with the address-of operator. Type decay (in the form of the implicit function-to-pointer conversion) does not apply to non-static member functions:
b = &collection_of_funcs::func_1;
http://eel.is/c++draft/conv#func

- If your class type is really named "collection_of_functions", get rid of it and create a namespace. It is a design mistake to use a class merely to group names.

- Are you aware of std::function? Pointer-to-member functions have idiosyncrasies which can be eliminated from the user's perspective.

ptr_to_chosen_func is a member type of collection_of_funcs; choose_func is also a member function.
collection_of_funcs::ptr_to_chosen_func b = ptr->choose_func(1);

- Do not dynamically-allocate memory just because you can. Dynamic allocation complicates the code, is slower, and (especially in the form of naked new and delete) has detrimental effects on exception safety.
1
2
3
collection_of_funcs fns;
auto pmf = fns.choose_func(1);
(fns.*pmf)();


See:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>

struct collection_of_funcs {
    using ptr_to_chosen_func = void(collection_of_funcs::*)();

    ptr_to_chosen_func choose_func(int);
    
    void func_1() { std::cout << "breed unicorns\n";  }
    void func_2() { std::cout << "destroy planets\n"; }
};

int main() {
    collection_of_funcs fns ;
    auto pmf = fns.choose_func(1);
    (fns.*pmf)();
}

collection_of_funcs::ptr_to_chosen_func 
collection_of_funcs::choose_func(int a){   
    if (a == 1) { return &collection_of_funcs::func_1; }
    else        { return &collection_of_funcs::func_2; }
}

http://rextester.com/ZLOL17756
Last edited on
thank you!

this was extremely helpful

I am a bit new to programming - so a bit unfamiliar with what a good design practice is.

I had a think re whether I really need the class for functions and ended up changing it to a namespace
Topic archived. No new replies allowed.