Archived

This topic is now archived and is closed to further replies.

Function Pointer problem. Need help with OOP.

This topic is 5578 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello, I''m still somewhat new to programming C++ an dI''m having a bit of trouble with Function Pointers. It''s best if I show an example: struct Painter { Painter(); virtual ~Painter(); BOOL Paint_16(); BOOL Paint_24(); BOOL Paint_32(); BOOL (*Paint)(); }; Whenever I try to assign the (*Paint) pointer to point to one of the other ''Paint'' functions it gives me an error that I''m trying to mix two incompatible pointers. Example: Painter *Artist = new Painter; Artist->Paint = Artist->Paint_32; I can get the pointers to work if I rewrite the structure like this: struct Painter { Painter(); virtual ~Painter(); BOOL Paint_16(); BOOL Paint_24(); BOOL Paint_32(); BOOL (Painter::*Paint)(); }; And then assign the function pointer to point to one of the other paint functions: Painter *Artist = new Painter; Artist->Paint = Artist->Paint_32; But then I still cannot use the (*Paint) function: Artist->Paint(); It gives me an error saying that the ''term does not evaluate to a function''. I can use the function pointers perfectly well if I keep the function pointer and the function the pointer points to out of the structure entirely, but is there any way to use Function Pointers within a structure? Any help would be greatly appreciated. - Obsidian Kindragon

Share this post


Link to post
Share on other sites
quote:
Original post by Alpha_ProgDes
I thought you couldn''t have function or function pointers, for that matter, in a struct, only member variables. Classes are for those things (functions). Right?


In C++, a struct is just a class with the default access set to public, instead of private.

So in C++, a struct can do anything a class can do.

Share this post


Link to post
Share on other sites
Try it like this:


struct Painter
{
Painter();
virtual ~Painter();
BOOL __cdecl Paint_16();
BOOL __cdecl Paint_24();
BOOL __cdecl Paint_32();
BOOL __cdecl (*Paint)();
};

And call Paint like this:

Artist.*Paint();

EDIT:

That may need to be
BOOL __cdecl (Painter::*Paint)();
instead of
BOOL __cdecl (*Paint)();


[edited by - TravisWells on September 10, 2002 3:47:40 PM]

Share this post


Link to post
Share on other sites
struct Painter
{
Painter();
virtual ~Painter();
BOOL Paint_16();
BOOL Paint_24();
BOOL Paint_32();
BOOL (*Paint)();
};

Painter Start, *pArtist;


Painter *Artist = new Painter;
pArtist->Paint = Start.Paint_32( );


.... i''m not exactly i just through this out... maybe it might give you an idea.

Share this post


Link to post
Share on other sites
I found out that I can access the (Painter::*Paint) function within other memebr functions of the class/structure. All I need to call the function is this:

(*this.*Paint)();

I still have the problem of not being able to us the (Painter::*Paint) function outside of the class/structure, but I think if I wasn't usign the 'Artist' as a pointer to a Painter then I would access the (Painter::*Paint) function outside of the class/structure like this:

Painter Artist;
Artist.Paint = Artist.Paint_32;
(Artist.*Paint)();

Or so the site Melraidin linked us to leads me to believe. But with my using the Artist as only a pointer to a Painter Object that doesn't seem to work. Neither does this:

Painter *Artist = new Painter;
Artist->Paint = Artist->Paint_32;
(Artist->*Paint)();

Or this:

(*Artist.*Paint)();

Which I thought one of which would a valid reference to the function pointer.

[edited by - Obsidian Kindragon on September 10, 2002 4:10:45 PM]

Share this post


Link to post
Share on other sites
Why not derive a class from Painter for each type of Paint function (16, 24 and 32), make Paint virtual.

Of course, you can''t change the function at runtime unless you recreate the object. But that shouldn''t be a problem.

----------------
Blaster
Computer game programmer and part time human being
Strategy First - http://www.strategyfirst.com
BlasterSoft - http://www.blastersoft.com

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
I don''t think there''s a way to call a pointer-to-member function pointer that''s inside a class/struct from outside the class/struct directly. (If I''m wrong on this, I''d really like to know how to do it.)

You have to wrap it inside a function call:


  
struct Painter
{
BOOL (Painter::*pfPaint)();
BOOL Paint() { return (this->*pfPaint)(); }
};


The compiler might be able to inline that, I don''t know. I do believe that''s your only option, however.

Share this post


Link to post
Share on other sites
I know one way which looks fugly..

      
struct Painter {
BOOL Paint_32();
BOOL (Painter::*Paint)();
};
//...

Painter *artist = new Painter();
artist->Paint = &Painter::Paint_32;
(artist->*(artist->Paint))();

The point being, artist->Paint points to the same 'function name' within any object of type Painter (or it's subclasses). You could e.g. use

              
Painter *artist = new Painter();
Painter *meh = new Painter();
artist->Paint = &Painter::Paint_32;
(meh->*(artist->Paint))();

to call meh-object's Paint_32()-function.

[edited by - civguy on September 10, 2002 4:31:09 PM]

Share this post


Link to post
Share on other sites
Why not do what Blaster suggested and make your life much easier?

I.E:


class CPainter
{

virtual BOOL paint( void );

};

class CPaint16 : public CPainter
{

BOOL paint( void )
{

// your paint_16() code goes here

}

};

class CPaint24 : public CPainter
{

BOOL paint( void )
{

// your paint_24() code goes here

}

};

class CPaint32 : public CPainter
{

BOOL paint( void )
{

// your paint_32() code goes here

}

};


And then in your code:

CPaint32 paint32Bucket;
CPainter *painter;

painter = &paint32Bucket;
painter.paint(); // this will call the paint32() routine


Hope this helps!

-G|aD-

[edited by - Gladiator on September 10, 2002 5:03:28 PM]

Share this post


Link to post
Share on other sites
Pointer to member function as function pointer:
see std::mem_fun_t, std::mem_fun_ref_t, etc.

You need a binder-type method that allow you to call the member function as though it was a global function. I posted a pseudo-example (I left out the trinary binder needed in that implementation) here, as well as an alternative using function objects.

Share this post


Link to post
Share on other sites

  
# include <iostream>

using std::cout;
using std::endl;

struct my_class
{
void function1 () { cout << "function1" << endl; }
void function2 () { cout << "function2" << endl; }
};

typedef void (my_class::* operation) ();

operation a = &my_class::function1;
operation b = &my_class::function2;

int main ()
{
// example 1 - through object


my_class mc;

(mc.*a) ();
(mc.*b) ();

// example 2 - through pointer


my_class* p = &mc;

(p->*a) ();
(p->*b) ();
}


Enjoy.

Share this post


Link to post
Share on other sites
to answer the original poster & giving reasons:

      
struct Painter
{
Painter() : Paint = Paint_32 { } // default uses Paint_32,

// but you can change this

// later

BOOL Paint_16();
BOOL Paint_24();
BOOL Paint_32();
BOOL (Painter::*Paint)(); // pointer to Paint member function of

// this signature

};

// free "doPaint" function as example:

void doPaint (Painter *p)
{
(p->*p->Paint) ();
}


As to why this works:
->* is a pointer-to-member operator. If p was a reference (Painter &p), you'd use .* instead of ->*
p->Paint is the member of Paint that is the pointer. You could alternatively write it like this, broken down into two parts for more clarity:

              
void doPaint (Painter *p)
{
BOOL (Painter::*pmf)() = p->Paint; // pmf is pointer to member func

(p->*pmf) (); // call pmf using p as 'this'

}

That might be a little more clear because the pointer-to-member function is more explicit here. The reason that you need p in the pointer-to-member operator is that member functions--as opposed to free functions--need a 'this'. There's basically an implicit argument which is the object, which is why you call pmf with p. Even though it looks like p->*pmf, you're really calling pmf with 'p' as the hidden 'this' argument to pmf.


[edited by - Stoffel on September 10, 2002 7:16:13 PM]

Share this post


Link to post
Share on other sites
I think a base class & virtual would solve this problem with less work than using method pointers, and both have the same overhead.

IPainter
{
virtual ~IPainter(){}
virtual BOOL Paint(/*put params here*/)=0;
};

CPainter16 : IPainter
{
virtual BOOL Paint(/*put params here*/)
{//16bit blit
}
};

CPainter24 : IPainter
{
virtual BOOL Paint(/*put params here*/)
{//24bit blit
}
};

//elsewhere in the code:
IPainter* painter;
switch(bpp)
{
case 16:
painter = new CPainter16;
break;
case 24:
painter = new CPainter24;
break;
case 32:
painter = new CPainter32;
break;
}

painter->Paint(...);

Share this post


Link to post
Share on other sites