PDA

View Full Version : Heh, another C++ Question...



2
03-26-2001, 09:57 AM
I am using GLUT to create a program to check my math for some 3d stuff. Anyway, for my callback functions I have created a baseclass "CDisplayMode". And then each derrived class has the functions necessary to display different things (ie, Verteces, Bezier Patches, etc). I used 'static' on all the functions, so they could be used by a global function. However, the way I store the functions is in an array of type CDisplayMode. And when I set one of the callback functions, instead of being tye derrived class's function, it's the function in CDisplayMode.

Pretty much, virtual would fix this, but I need the static, and you can't have a function with both virtual and static.

Help! Thanks.

DFrey
03-26-2001, 11:31 AM
Ummm, I'm not understanding why you can't use virtual methods. Something like the following would surely work fine.




class GrObject {
public:
virtual void Draw()=0;
};

class GrPoint:public GrObject {
public:
void Draw();
};

class GrTriangle:public GrObject {
public:
void Draw();
};

class GrTriangleSoup:public GrObject {
public:
void Draw();
};

class GrBezierPatch:public GrObject {
public:
void Draw();
};


Then your global function would access an array of GrObject pointers and simply call the Draw method to draw them. For example:




int num_objects;
GrObject **objects=GetObjectArray(&num_objects);
if(objects){
for(int j=0;j<num_objects;++j)
objects[j]->Draw();
}



Of course I left out details like constructors and such because it is obvious you will need them.

[This message has been edited by DFrey (edited 03-26-2001).]

2
03-26-2001, 01:20 PM
Because I'm using GLUT. And GLUT callbacks use Function Pointers. And you can't use a class-function for a global function pointer without static. Or so I have been told.

DFrey
03-26-2001, 01:44 PM
Ah, GLUT callbacks, ok that makes sense. In that case you may be able to use the so called template design pattern. I'm unfamiliar with GLUT, but in your callback functions, can you pass a pointer to the object? For example:




class GrObject{
public:
static void DrawObj(void *object);
virtual void Draw();
};

class GrPoint:public GrObject{
public:
void Draw();
};

void GrObject::DrawObj(void *object){
((GrObject *)object)->Draw();
}


Then use DrawObj as your callback.


[This message has been edited by DFrey (edited 03-26-2001).]

2
03-26-2001, 07:28 PM
Because the callback func doesn't have the "void *object" parameter. =)

This is pretty much how GLUT callbacks works. You register functions through a function that GLUT has defined. Then you call glutMainLoop() and GLUT runs, and calls the function you passed in initialization when it's supposed to be called. Example:

void cbKeyboard( unsigned char key, int x, int y ) { }

glutKeyboardFunc( cbKeyboard );
glutMainLoop();

Now, whenever a key is pressed, glut calls "cbKeyboard". There are a bunch of callback funcs, and I have a few different modes (in which different things are drawn, and therefore have different callbacks) in my program, so I made a class that contains all the necessary funcs. Then the baseclasses define those funcs for each different mode. Then, instead of a massive switch setting everything, I create an array filled with one of every kind of mode. Then I just use a number representing the mode i'm in, and cycle through the array with ease, and without the huge switch.

The problem, as I said before, is that the functions HAVE to be static, so that the global callback funcs can use them. However, they also HAVE to be virtual, so that when the callback calls them, it uses the highest applicable class on the baseclass hierarchy (as opposed to ALWAYS using the baseclass function). However, you cannot have a function with both virtual and static.

I was (and am) hoping that there is a simple way around this that I haven't thought of, or I didn't know. Again, any help would be greatly appreciated. Thanks!

[This message has been edited by 2 (edited 03-26-2001).]

john
03-26-2001, 08:30 PM
Hello,
nope, changed my mind. I've talked about this problem with a colleague in the lab, and the answer is: no, you can NOT pass virtual functions to glut, for several reasons:

1) virtual functions are associated with objects, and there is no way the glut callback knows what *this is.
2) virtual functions also need lookuptables to work out what function to call based on the pointer to this.
3) the syntax i had in the prev post is just wrong. the type of a virtual function is hideously mangled.

since glutcallbacks do NOT know of the this ptr, then it is impossible to call your virtual func. feh.

a solution, however, is to have a wrapper class. eg:

class base {
public:
virtual void draw(void);
};

base *someglobalobject;

class deriv : public base {
puvlic:
void draw(void);
static void wrapper(void)
{
someglobalobject->draw();
}
};

or something like that. the trick is you give glut a static function that it CAN work the address of, and it uses the function to dispatch the C++ code.

cheers
John

(thanks to Darren for his insight)

2
03-27-2001, 07:33 AM
Ah, now that's a good idea. In fact, that works perfectly with my code. I'll just have all the derrived classes and stuff, then, since I have one of each, I'll just create a global function which calls them. Thanks a bunch!