C++ calling a function from a vector of function pointers inside a class where the function definition is in main

47,855

Solution 1

Your code is almost correct. Your vector is mistakenly holding pointers to pointers to functions rather than simply pointers to functions. addThingy is adding the address of the function pointer in to the vector, but that pointer goes out of scope in the next line.

Change your code as follows:

//Store pointers to functions, rather than
//pointers to pointers to functions
std::vector<void (*)()> vectoroffunctions;

SomeClass::addThingy(void (*function)())
{
    //Don't take the address of the address:
    vectoroffunctions.push_back(function);
}

Also, you have a lot of syntax errors in the rest of the code which should stop the code from even compiling.

Solution 2

The problem is here:

vectoroffunctions.push_back(&function);

You're adding address of the local variable. The local variable gets destroyed once you return from the function. The address which the vector stores points to a destroyed object which is why you get "access violation" error at runtime.

To fix this, do this:

First change this

std::vector<void (**)()> vectoroffunctions;

to this:

std::vector<void (*)()> _functions; //vector of function-pointer-type
                                    //I changed the name also!

which is practically same as:

std::vector<void()> _functions; //vector of function-type

Now do this:

_functions.push_back(function); //add copy! 

To make it more flexible, you could use template along with std::function as:

class A
{
    public:
        template<typename Function>
        void add(Function && fn) 
        {  
            _functions.push_back(std::forward<Function>(fn)); 
        }
        void invoke_all()
        {
           for(auto && fn : _functions)
                fn();
        }
    private:
        std::vector<std::function<void()>> _functions;
};

Now you can use it to store functions as well as functors:

void myfunction() { std::cout << "myfunction" << std::endl ; }

struct myfunctor
{
       void operator()() { std::cout << "myfunctor" << std::endl ; }
};

A a;
a.add(myfunction);   //add function
a.add(myfunctor());  //add functor!
a.invoke_all();

Output (Online Demo):

myfunction
myfunctor

Hope that helps.

Solution 3

Function pointers are much more legible with typedefs:

typedef void (*RequiredFunction)();

Then you can declare addThingy() like this:

    void addThingy(RequiredFunction function);

And vectoroffunctions like so:

    std::vector<RequiredFunction> vectoroffunctions;

The definition of addThingy will be:

void SomeClass::addThingy(RequiredFunction function)
{
    vectoroffunctions.push_back(function);
}

And your main() would look more like:

int main()
{
    SomeClass sc;
    RequiredFunction pointerfunc = somefunction;
    sc.addThingy(pointerfunc);
    sc.actionWithDiffrentOutcomes();
}

Far fewer *s and &s with which to make mistakes!

Share:
47,855
Steven Venham
Author by

Steven Venham

I write code. and code accessories. C, C++, Arduino, game engines.

Updated on July 09, 2022

Comments

  • Steven Venham
    Steven Venham almost 2 years

    Alright, in my main i have:

    void somefunction();
    int main()
    {
        //bla bla bla
        SomeClass myclass = SomeClass();
        void(*pointerfunc)() = somefunction;
        myclass.addThingy(pointerfunc);
    
        //then later i do
        myclass.actionWithDiffrentOutcomes();
    }
    
    void somefunction()
    {
        //some code
    }
    

    and in the class:

    class SomeClass()
    {
        public:
            void addThingy(void (*function)());
            void actionWithDiffrentOutcomes();
        private:
            std::vector<void (**)()> vectoroffunctions;
    }
    SomeClass::addThingy(void (*function)())
    {
        vectoroffunctions.push_back(&function);
    }
    SomeClass::actionWithDiffrentOutcomes()
    {
        (*vectoroffunctions[0])();;
    }
    

    I'm sort of new-ish to pointers, but I read over my c++ books, googled, ext. and this seems correct, compiles, runs but when I call "actionWithDiffrentOutcomes()" I get an access violation. I'm not sure what to do. it seems correct, but something is obviously wrong. So how can I call a function from within a class when the definition is in another?

    I'm doing it this way because i cannot hard-code every option into a switch statement.

  • Steven Venham
    Steven Venham about 11 years
    Ah thank you, that makes more sense. Also, sorry about the syntax, I copied it into np++ to post it here rather then post my entire program.
  • Sid Sarasvati
    Sid Sarasvati almost 11 years
    Any elegant solution for functions with variable arguments?
  • Nawaz
    Nawaz almost 11 years
    @sid: What is the use case?
  • serup
    serup over 4 years
    How would you cleanup? you add functions / functors, but what to do when class object is destroyed ?