Jeremy Trifilo
Jeremy Trifilo

Reputation: 29

Function calls with class members?

Before I present the code which is found at the bottom of this post I would like to talk about the issue and the fix's that I do not desire. Okay basically I've created a GUI from scratch sort of and one requirement I wanted for this was allow components to have their own click executions so if i click a button or tab etc.. It would call Component->Execute(); Well normally you would do something like a switch statement of ids and if that components ID equaled n number then it would perform this action. Well that seemed kinda dumb to me and I thought there has to be a better way. I eventually tried to incorporate a feature in JAVA where you would do like Component.AddActionListener(new ActionListener( public void execute(ActionEvent ae) { })); or something like that and I thought that this feature has to be possible in C++. I eventually came across storing void functions into a variable in which could be executed at any time and modified at any time. However I hadn't noticed an issue and that was this only worked with static functions. So below you'll see my problem. I've patched the problem by using a pointer to SomeClass however this would mean having an individual function call for every class type is there no way to store a function callback to a non-static class member without doing the below strategy? and instead doing a strategy like the commented out code?

//Main.cpp

#include <iostream> //system requires this.
#include "SomeClass.h"

void DoSomething1(void)
{
    std::cout << "We Called Static DoSomething1\n";
}

void DoSomething2(void)
{
    std::cout << "We Called Static DoSomething2\n";
}

int main()
{
    void (*function_call2)(SomeClass*);
    void (*function_call)() = DoSomething1; //This works No Problems!
    function_call(); //Will Call the DoSomething1(void);
    function_call = DoSomething2; //This works No Problems!
    function_call(); //Will Call the DoSomething2(void);

    SomeClass *some = new SomeClass(); //Create a SomeClass pointer;
    function_call = SomeClass::DoSomething3; //Static SomeClass::DoSomething3();
    function_call(); //Will Call the SomeClass::DoSomething3(void);
    //function_call = some->DoSomething4; //Non-Static SomeClass::DoSomething4 gives an error.
    //function_call(); //Not used because of error above.
    function_call2 = SomeClass::DoSomething5; //Store the SomeClass::DoSomething(SomeClass* some);
    function_call2(some); //Call out SomeClass::DoSomething5 which calls on SomeClass::DoSomething4's non static member.
    system("pause");
    return 0;
}

//SomeClass.hpp

#pragma once

#include <iostream>

class SomeClass 
{
    public:
        SomeClass();
        ~SomeClass();

    public:
        static void DoSomething3(void);
        void DoSomething4(void);
        static void DoSomething5(SomeClass* some);
};

//SomeClass.cpp

#include "SomeClass.h"

SomeClass::SomeClass(void)
{

}

SomeClass::~SomeClass(void)
{

}

void SomeClass::DoSomething3(void)
{
    std::cout << "We Called Static DoSomething3\n";
}

void SomeClass::DoSomething4(void)
{
    std::cout << "We Called Non-Static DoSomething4\n";
}

void SomeClass::DoSomething5(SomeClass *some)
{
    some->DoSomething4();
}

Secondary Fix for what I'll do not an exact answer I wanted but it meets my needs for now along with allowing additional features which would have become overly complicate had this not existed.

//Component.hpp

#pragma once

#include <iostream>
#include <windows.h>
#include <d3dx9.h>
#include <d3d9.h>

#include "Constants.hpp"
#include "ScreenState.hpp"
#include "ComponentType.hpp"

using namespace std;

class Component 
{

    static void EMPTY(void) { }
    static void EMPTY(int i) { }

    public:
    Component(void)
    {
        callback = EMPTY;
        callback2 = EMPTY;
        callback_id = -1;
    }

    Component* SetFunction(void (*callback)())
    {
        this->callback = callback;
        return this;
    }

    Component* SetFunction(void (*callback2)(int), int id)
    {
        this->callback_id = id;
        this->callback2 = callback2;
        return this;
    }

    void execute(void)
    {
        callback();
        callback2(callback_id);
    }

}

Upvotes: 0

Views: 144

Answers (1)

Kerrek SB
Kerrek SB

Reputation: 476950

The syntax for pointers-to-member-functions is as follows:

struct Foo
{
    void bar(int, int);
    void zip(int, int);
};

Foo x;

void (Foo::*p)(int, int) = &Foo::bar;   // pointer

(x.*p)(1, 2);                           // invocation

p = &Foo::zip;

(x.*p)(3, 4);                           // invocation

Mind the additional parentheses in the function invocation, which is needed to get the correct operator precedence. The member-dereference operator is .* (and there's also ->* from an instance pointer).

Upvotes: 1

Related Questions