954,535 Members — Technology Publication meets Social Media
Username:
Password:
Lost login information?
Have something to say? Contribute New Article Reply to this Article

callbacks and class member functions...

i have a BaseClass and a DerivedClass. i need the BaseClass to register a glut callback, but i need the DerivedClass to determine what the callback does.

heres the code:

(.h)

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

protected:
static void _renderCallback(void);

virtual void Render();
};

(.cpp)

BaseClass::_renderCallback(void)
{
Render();
}

BaseClass::Render()
{
//override me in the DerivedClass !
}


i understand that if the callback is within a class, it must be declared as static, and it cannot be virtual. but of course i get compile time errors with this code - "in function 'BaseClass::_renderCallback(void)':
cannot call member function 'BaseClass::Render' without object".

so how to enable the callback to call a function that can be overriden in the derived class?

unclepauly
Light Poster
42 posts since Dec 2006
Reputation Points: 16
Solved Threads: 0
 

well ive been doing a bit of reseach on this and it looks nasty. declaring the callback as static gets rid of the 'this' pointer, (so registering it as a callback is fine), but because of this it cant access any of the other members of the class! so its pretty useless.

so i guess this changes the question slightly. how to make the static function access the other members of the class? can it be done?

unclepauly
Light Poster
42 posts since Dec 2006
Reputation Points: 16
Solved Threads: 0
 
so i guess this changes the question slightly. how to make the static function access the other members of the class? can it be done?


You can't. Static members are exactly that: static. They're the same throughout all instances of the class; in fact they don'tneed an instance to be used.

So let's say you call a static function. It's not going to have an object, so how the heck is it supposed to know which object to access from, even if you could do such a thing?

John A
Vampirical Lurker
Team Colleague
7,630 posts since Apr 2006
Reputation Points: 2,240
Solved Threads: 339
 

yes i see. bummer.

cheers though.

unclepauly
Light Poster
42 posts since Dec 2006
Reputation Points: 16
Solved Threads: 0
 

One way to get a static member access non-static methods is thru a static or global pionter or reference to the desired instance. Then the static member uses that pointer to access non-static methods and data objects.

Another method is to make static all the methods and objects that the static method needs to access.

Ancient Dragon
Retired & Loving It
Team Colleague
30,050 posts since Aug 2005
Reputation Points: 5,662
Solved Threads: 2,343
 
Another method is to make static all the methods and objects that the static method needs to access.

But I guess that would beat the purpose of designing class for creating objects since each object created would have the same thing inside of it (the member variables being static).

~s.o.s~
Failure as a human
Administrator
11,938 posts since Jun 2006
Reputation Points: 3,281
Solved Threads: 734
 
But I guess that would beat the purpose of designing class for creating objects since each object created would have the same thing inside of it (the member variables being static).

Yes it would -- but in some cases I can think of there is only a single instance of the class anyway and making everything static would only be useful in such a case.

Ancient Dragon
Retired & Loving It
Team Colleague
30,050 posts since Aug 2005
Reputation Points: 5,662
Solved Threads: 2,343
 

@Ancient Dragon => That is the right way of doing it. Declare your callback function to take the this pointer. Same mechanism used for thread functions as well.
But in this case caller has to get the this pointer. If there is a possibility to change the callback interface there is a cleaner soln..

Coming to the problem.
- There is no easy soln. if callback interface is fixed.
- One good/clean soln would be register the base class object as callback object instead of a callback function. This is more on lines of how Java does it. In most cases one needs to implement a callback interface in a Impl class, create an object of this Impl class and register the object for callback (instead of function). But all this is possible only if you have control over how to define the callback interface.

thekashyap
Practically a Posting Shark
811 posts since Feb 2007
Reputation Points: 254
Solved Threads: 75
 
@Ancient Dragon => That is the right way of doing it. Declare your callback function to take the this pointer. Same mechanism used for thread functions as well..

If you are writing your own interface then you may be able to use non-static class methods for callback functions. I've see this coded a couple times but don't recall exactly how its done. The problem is when you have to pass callback functions to a function that you did not write, such as win32 api and other library functions.

Ancient Dragon
Retired & Loving It
Team Colleague
30,050 posts since Aug 2005
Reputation Points: 5,662
Solved Threads: 2,343
 

Finally I think I found a soln. Let me know if it does what you need..
It's like a hybrid soln of the one using callback functions and one using callback objects. Idea is to register the derived class obj with base class. Advantage is base class's _renderCallback() can call a (non-static) function of the derived class.

#include <iostream>
#include <conio.h>    //getch()

using namespace std ;
//------------------------------------------------
class BaseClass
{
public:
    BaseClass() {}
    ~BaseClass() {}

    static void _renderCallback(void)
    { derivedClassObjPtr->Render(); }

protected:
    void set_derivedClassObjPtr( BaseClass* ptr )
    { derivedClassObjPtr = ptr ; }

    virtual void Render() = 0 ;

private:
    static BaseClass* derivedClassObjPtr ;
};

BaseClass* BaseClass::derivedClassObjPtr = NULL ;
//------------------------------------------------

class DerivedClass : public BaseClass
{
public:
    DerivedClass()
    { set_derivedClassObjPtr( this ) ; }
    ~DerivedClass() {}

protected:
    virtual void Render()
    { cout << "Inside DerivedClass::Render()" << endl ; }
};
//------------------------------------------------

typedef void(*t_CallBackFunction)() ;
t_CallBackFunction theCallbackFunc ;

void callback_registration_function( t_CallBackFunction func )
{ theCallbackFunc = func ; }

void trigger_callback()
{ theCallbackFunc(); }
//------------------------------------------------

int main ()
{
    DerivedClass obj ;
    callback_registration_function( BaseClass::_renderCallback ) ;
    trigger_callback() ;

    //-----------------------
    getch() ;
    return 0;
}
//------------------------------------------------
thekashyap
Practically a Posting Shark
811 posts since Feb 2007
Reputation Points: 254
Solved Threads: 75
 

This article has been dead for over three months

Post: Markdown Syntax: Formatting Help
You