Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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.

like image 925
Steven Venham Avatar asked Feb 28 '13 05:02

Steven Venham


People also ask

How do you call a function from a pointer object?

Using a pointer-to-member-function to call a function Calling the member function on an object using a pointer-to-member-function result = (object. *pointer_name)(arguments); or calling with a pointer to the object result = (object_ptr->*pointer_name)(arguments);

What does a pointer to a function point to in C?

A pointer to a function points to the address of the executable code of the function. You can use pointers to call functions and to pass functions as arguments to other functions.

Can we call member function using this pointer from constructor in C++?

the constructor is the first function which get called. and we can access the this pointer via constructor for the first time. if we are able to get the this pointer before constructor call (may be via malloc which will not call constructor at all), we can call member function even before constructor call.

Which operator is used with pointer to point towards a member function of a class?

The pointer to member operators . * and ->* are used to bind a pointer to a member of a specific class object.


3 Answers

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.

like image 28
Nawaz Avatar answered Oct 19 '22 07:10

Nawaz


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.

like image 107
Mankarse Avatar answered Oct 19 '22 07:10

Mankarse


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!

like image 29
Johnsyweb Avatar answered Oct 19 '22 06:10

Johnsyweb