Archived

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

Viajero

address of a class member function

Recommended Posts

Hi once again I got another problem with pointers (some day I''ll get them down..) This is what it basicly the trouble maker looks like :
Class1.func( Class2.func );
 
The compiler doesn''t recognize the type of the parameter and gives an error somewhat like this: "No match for Class1::func({unknown type}) candidates are..." Am I trying to pass the address incorrectly or..?

Share this post


Link to post
Share on other sites
Ok, here''s all the relevant information (and a bit more) :

  
class CHAR {
...
void draw_char(CHAR *p, void (*draw)(char, int, int, int, int, int)) //p = player

{ //line 91 of classes.h

...
}
...
};

class GBITMAPS {
...
void drawskin(char b, int skin, int frame, int x, int y, int a)
{
...
}
...
};

//the mother function of the classes =>

{
...
CHAR *chars;
GBITMAPS gfx;
...
chars = new CHAR[1+map.npccount];
...
chars[0].draw_char(&chars[0], gfx.drawskin); //line 58 of game.h

...
}

=>

game.h:58: no matching function for call to ''CHAR::draw_char (CHAR *, {unknown type})''
libs/classes.h:91: candidates are: void CHAR::draw_char(CHAR *, void (*)(char, int, int, int, int, int))

Share this post


Link to post
Share on other sites
You're declaring the function draw_char to accept a pointer to a GENERAL function, whereas you pass to it the address of a CLASS MEMBER function. This will not work. You have to declare your draw_char function to accept a pointer to a member function of class GBITMAPS. To do this change your draw_char declaration to the following:

void draw_char(CHAR *p, void (GBITMAPS::*draw)(char, int, int, int, int, int))

Also you will need to change gfx.drawskin to GBITMAPS::drawskin if you want to call the function through its pointer AND through an instanced object. If you do so the pointer will get its offset in the class rather than its actual address in memory allocated for an instanced object, so you can use the pointer with an object. Otherwise you can leave it as it is and use the pointer as a pointer to the particular function belonging to the object gfx.



[edited by - VXG on January 29, 2003 4:04:37 PM]

Share this post


Link to post
Share on other sites
quote:
Original post by VXG
void draw_char(CHAR *p, void (GBITMAPS::*draw)(char, int, int, int, int, int))


Cheers. That kind of thing crossed my mind. Though I probably shouldn''t be messing around with stuff like this to begin with, since all my C++ knowledge is from a very limited quick C++ tutorial in LaMonthe''s Tips And Tricks of the Windows Game Programming Gurus.. :/

quote:
Also you will need to change gfx.drawskin to GBITMAPS::drawskin

So I guess I should then pass the address like this? :
chars[0].draw_char(&chars[0], &GBITMAPS::drawskin);
But how would I then call the pointed function of a specific GBITMAPS class from the chars[0].draw_char function? Or do you mean I need to change the definition of the pointed member function (of GBITMAPS)?

I promise, next time I run into trouble I''m gonna go and buy a C++ book..

Share this post


Link to post
Share on other sites
Here''s the deal...

Let''s say you have the following class:

class X
{
public:

int TheFunction(int a, int b)
{
return (a+b);
}

};

Then you make an instanced object of this class:

X TheObject;

Now you would like to declare a pointer through which you can access TheFunction in your class. There are two ways of doing so:

- The first way is to declare a pointer to a member function of class X and use it to point to a PARTICULAR instance of this function in a PARTICULAR instanced object. In order to do this you assign to it the address of a particular function instance. In this case it is TheObject.TheFunction, which means that it will point to the instance of TheFunction in TheObject ONLY. This is how to do it:

int (X::*ThePointer) (int, int);

ThePointer = TheObject.TheFunction;

Note that you need to type ONLY the function name without its return type etc. and WITHOUT the & operator to get its address.

- The second way to do it is to again declare a pointer to a class member function, but in this case you can use it to point to ANY instance of TheFunction in ANY object of class X. To do this you need to get the offset of TheFunction in the class X instead of its address. This means that the pointer can be invoked on ANY object to access this particular object''s copy of TheFunction. It will do this by counting to the offset that is stored in it and invoking the code it finds at that offset. This is how to do it:

int (X::*ThePointer) (int, int);

ThePointer = X::TheFunction;

Notice the difference between the pointer assignments in the two cases. In the first case it was assigned a particular address. In the second case it was assigned the number of bytes to count from the first byte of an object stored in memory in order to get to the required piece of code. This way it can be called on any instanced object:

X Object1, Object2;

int x = 1, y = 2, z;

z = (Object1.*ThePointer)(x, y);

z = (Object2.*ThePointer)(y, x);

The brackets around the pointer call are needed for the compiler to interpret this as a function pointer.


Share this post


Link to post
Share on other sites
Now to solve your particular problem...

You must pass the address like this if you want your pointer to point to the function drawskin in the object gfx:

chars[0].draw_char(&chars[0], gfx.drawskin);

To store an offset in your pointer as described above you have to pass it like this:

chars[0].draw_char(&chars[0], GBITMAPS::drawskin);

OR

chars[0].draw_char(&chars[0], &GBITMAPS::drawskin);

The & operator,when it comes to functions,means that an offset is being stored in the pointer. Using the & operator is optional. To the compiler &GBITMAPS::drawskin and GBITMAPS::drawskin is the same thing.



Share this post


Link to post
Share on other sites
Thank you very much, I''m beginning to understand the whole deal.
Only chars[0].draw_char(&chars[0], gfx.drawskin); doesn''t seem to work for me.. =>

oject-dependent reference ''drawskin'' can only be used in a call to form a pointer to member function, say ''&GBITMAPS::drawskin''

here''s the pointer definition again :
void (GBITMAPS::*draw)(char, int, int, int, int, int)

drawskin function is also public. How I can fail to do this right when I have clear instructions is beyond me...

Share this post


Link to post
Share on other sites
The following code compiles without any errors in Visual C++ 6. The variations gfx.drawskin, GBITMAPS::drawskin and &GBITMAPS::drawskin all compile without errors.

----------------------------------------------------------------

class GBITMAPS;
//forward declaration of class GBITMAPS

class CHAR {
public:
void draw_char(CHAR *p, void (GBITMAPS::*draw)(char, int, int, int, int, int))
{
//function does nothing - it is just a test to see if it accepts parameters without compiler errors
}
};

class GBITMAPS {
public:
void drawskin(char b, int skin, int frame, int x, int y, int a)
{
//function does nothing
}
};


int main()
{
CHAR *chars;
GBITMAPS gfx;
chars = new CHAR[100];
chars[0].draw_char(&chars[0], gfx.drawskin);
return 0;
}

----------------------------------------------------------------

The problem could be with your compiler. Due to the final stage of standardizing C and C++ several years ago, many hickups occurred with compilers "reacting" differently to standard code. Therefore, this could be the problem. What compiler are you using?

Also, make sure that the GBITMAPS class is declared before you declare a pointer to one of its members, otherwise the compiler will not know about its existence when it encounters the pointer. You can do this by either placing the class declaration before the declaration of the pointer is encountered or by using a forward declaration as I have done in the code above.

Share this post


Link to post
Share on other sites
I got the same error from your code. It seems my good old friend DJGPP has finally let me down :/ At last a good excuse to switch to MSVC++. Thanks for your help

Share this post


Link to post
Share on other sites