![]() |
| | #1 |
| Registered User Join Date: Mar 2009
Posts: 8
| |
| CorX is offline | |
| | #2 |
| CSharpener Join Date: Oct 2006
Posts: 5,242
| it is just a general pointer passing to the function, your function should know what is the actual type of the pointer - and cast it apropriatly before accessing the data. It is mostly used in the Callbacks, when library is provided with CB address and some context address. Library does not need to know the type of the data - so the pointer is stored as void* and supplied to the CB, when it is called from the library code the CB - which is part of the application code - knows exactly what is the data type passed as a context and could cast the pointer accordingly
__________________ If I have eight hours for cutting wood, I spend six sharpening my axe. Last edited by vart; 03-17-2009 at 12:23 PM. |
| vart is offline | |
| | #3 |
| Registered User Join Date: Mar 2009
Posts: 8
| Thanks, I understand know. |
| CorX is offline | |
| | #4 |
| Guest Join Date: Aug 2001
Posts: 4,923
| This technique isn't used as often in C++ as it is in C, but there are certain situations where it's unavoidable. A typical usage is with callback functions. Lets say you have a shape-drawing library. You want to allow the user to decide what to do when a pixel needs to be drawn. You have no idea what data structures the client code requires to accomplish that so you simply have them pass a pointer to their data. Here's a somewhat contrived example: Code: // library code
typedef void ( * callback )( int, int, void* );
void draw_some_shape( rectangle* bounds, callback function, void* data )
{
for( int r = bounds->top; r < bounds->bottom; ++r )
for( int c = bounds->left; c < bounds->right; ++c )
if( inside( r, c ) )
callback( r, c, data );
}
// client code
struct image_data
{
int image[ HEIGHT ][ WIDTH ], color;
};
void draw_pixel( int row, int column, void* data )
{
image_data* image = ( image_data* )data;
image_data->image[ row ][ column ] = image_data->color;
}
int main( void )
{
image_data data;
data.color = hsv( 0.333, 0.5, 0.5 );
rectangle bounds;
bounds.top = HEIGHT / 2;
bounds.left = WIDTH / 2;
bounds.bottom = HEIGHT;
bounds.right = WIDTH;
draw_some_shape( &bounds, draw_pixel, &data );
// do something useful with the image
return 0;
}
Last edited by Sebastiani; 03-17-2009 at 12:41 PM. Reason: corrections |
| Sebastiani is offline | |
| | #5 | |
| C++ Witch Join Date: Oct 2003 Location: Singapore
Posts: 10,366
| Quote:
Code: // library code
template<typename T, typename Callback>
void draw_some_shape( const rectangle& bounds, Callback function, T& data )
{
for( int r = bounds.top; r < bounds.bottom; ++r )
for( int c = bounds.left; c < bounds.right; ++c )
if( inside( r, c ) )
function( r, c, data );
}
// client code
struct image_data
{
int image[ HEIGHT ][ WIDTH ], color;
};
void draw_pixel( int row, int column, image_data& data )
{
image_data.image[ row ][ column ] = image_data.color;
}
int main( void )
{
image_data data;
data.color = hsv( 0.333, 0.5, 0.5 );
rectangle bounds;
bounds.top = HEIGHT / 2;
bounds.left = WIDTH / 2;
bounds.bottom = HEIGHT;
bounds.right = WIDTH;
draw_some_shape( bounds, draw_pixel, data );
// do something useful with the image
return 0;
}
__________________ C + C++ Compiler: MinGW port of GCC Build + Version Control System: SCons + Bazaar Look up a C/C++ Reference and learn How To Ask Questions The Smart Way | |
| laserlight is online now | |
| | #6 | |
| Mysterious C++ User Join Date: Oct 2007
Posts: 14,099
| This can be avoided with template, as shown below: Code: // library code
template<typename T, typename Callback_t>
void draw_some_shape( rectangle* bounds, Callback_t function, T& data )
{
for( int r = bounds->top; r < bounds->bottom; ++r )
for( int c = bounds->left; c < bounds->right; ++c )
if( inside( r, c ) )
callback( r, c, data );
}
// client code
struct image_data
{
int image[ HEIGHT ][ WIDTH ], color;
};
void draw_pixel( int row, int column, image_data* data )
{
image_data->data[ row ][ column ] = image_data->color;
}
int main()
{
image_data data;
data.color = hsv( 0.333, 0.5, 0.5 );
rectangle bounds;
bounds.top = HEIGHT / 2;
bounds.left = WIDTH / 2;
bounds.bottom = HEIGHT;
bounds.right = WIDTH;
draw_some_shape( &bounds, &draw_pixel, &data );
// do something useful with the image
return 0;
}
__________________ Using: Microsoft Windows™ 7 Professional (x64), Microsoft Visual Studio™ 2008 Team System I dedicated my life to helping others. This is only a small sample of what they said: "Thanks Elysia. You're a programming master! How the hell do you know every thing?" Quoted... at least once. Quote:
| |
| Elysia is offline | |
| | #7 |
| Senior software engineer Join Date: Mar 2007 Location: Portland, OR
Posts: 5,381
| The method you and Laserlight are talking about is definitely a good one, but it still, in theory, allows the possibility for the callback driver to poke around inside the T object when it shouldn't. In practice, this would be extremely difficult because you don't know what's in there, but a void * completely guarantees that the code won't touch it, since it has no idea what type it is (even as a template parameter). Normally though, I'd define a callback API like this: Code: class Callback
{
public:
virtual ~Callback() {}
virtual void DoIt() = 0;
};
void DriveTheCallback(Callback *cb)
{
cb->DoIt();
}
__________________ "Congratulations on your purchase. To begin using your quantum computer, set the power switch to both off and on simultaneously." -- raftpeople@slashdot |
| brewbuck is offline | |
| | #8 | |
| Mysterious C++ User Join Date: Oct 2007
Posts: 14,099
| Well, I suppose that may be, but then we would get into X vs Y. Your solution might hide the object, but it's also slower due to being dynamic polymorphism as opposed to static polymorphism. It also means more work, but hey, no solution is ever perfect.
__________________ Using: Microsoft Windows™ 7 Professional (x64), Microsoft Visual Studio™ 2008 Team System I dedicated my life to helping others. This is only a small sample of what they said: "Thanks Elysia. You're a programming master! How the hell do you know every thing?" Quoted... at least once. Quote:
| |
| Elysia is offline | |
| | #9 |
| Senior software engineer Join Date: Mar 2007 Location: Portland, OR
Posts: 5,381
| Static polymorphism would not allow for loading a plug-in which might implement the callback. Yep, always a tradeoff.
__________________ "Congratulations on your purchase. To begin using your quantum computer, set the power switch to both off and on simultaneously." -- raftpeople@slashdot |
| brewbuck is offline | |
![]() |
| Tags |
| args, pointers, void |
| Thread Tools | |
| Display Modes | |
|