void pointers in C++
I saw this example on a website, and the websites mentions:- "One of its uses (void pointers) may be to pass generic parameters to a function"
// increaser
#include <iostream>
using namespace std;
void increase (void* data, int psize)
{
if ( psize == sizeof(char) )
{ char* pchar; pchar=(char*)data; ++(*pchar); }
else if (psize == sizeof(int) )
{ int* pint; pint=(int*)data; ++(*pint); }
}
int main ()
{
char a = 'x';
int b = 1602;
increase (&a,sizeof(a));
increase (&b,sizeof(b));
cout << a << ", " << b << endl;
return 0;
}
wouldn't it be simpler to write code like the following?
void increaseChar (char* charData)
{
++(*charData);
}
void increaseInt (int* intData)
{
++(*intData);
}
int main ()
{
char a = 'x';
int b = 1602;
increaseChar (&a);
increaseInt (&b);
cout << a << ", " << b << endl;
str开发者_如何学运维ing str;
cin >> str;
return 0;
}
It is less code, and really straightforward. And in the first code I had to send the size of the data type here I don't!
It would be best to make the function type safe and generic. It would also be best to take the argument by reference instead of by pointer:
template <typename T>
void increment(T& data) {
++data;
}
void*
should be avoided wherever possible in C++, because templates and inheritance provide type-safe alternatives.
Your solution works only for int or char. Consider the situation you want to go through array of some custom type( struct, for example ). In your code you will need to add a method to do that, however in the example above no line of could should be added to get the work example.
"One of its uses (void pointers) may be to pass generic parameters to a function"
Not a good-style use, to be certain. Passing generic parameters to functions is done by:
a) templates (and possibly template specializations) which allows to write safe code,
b) OOP approaches.
I like your second increaseInt
and increaseChar
solution better. You can rewrite it as:
template<typename T>
void increase(T* pData)
{
++(*pData);
}
It will work for any type which supports ++
and be safe.
Sometimes you'd still need a void pointer as a "generic parameter" - for example when using the popular pthread
library. When you spawn a thread, you may send it some arbitrary data (of any type you want), and it's done using - well - a void*
pointer. The pthread
library is in C not C++, which may be one of the reasons, but you might want to interface with it from C++ and this will indeed require you to use the void*
pointer as a "generic type". Not much harm done there, though; just remember that for everyday coding there are more elegant solutions.
Actually I think the example is quite bad. One of the canonical examples would be the C library's qsort
, where you pass in void*
as well as a function which interprets the data.
However, in C++, there are better mechanisms available which are less likely to silently malfunction.
Hence, the use of void*
to pass generic data around should probably be limited to
- instances where code bloat is important, and
- code which interacts with other language, in particular C.
When you are programming C (not C++) void* is you only way to do something generic. Nevertheless the example is terrible. This scheme is often used for callback mechanics, where you pass a function pointer and a void*. For example:
void handle_crash(void* data)
{
Log* log = (Log*)data;
log->print("We crashed.");
}
Log log;
set_crash_handler(&handle_crash, &log);
You will see this often on C frameworks such as libxml2 or spidermonkey. In the case of C this is the only thing there is to accomplish it. It is not a very robust solution.
In case you are working with C++ you have more options. Basic generic programming can be done with templates or overloading as mentioned in other answers. In case you need solid callback mechanic you might want to look into libsigc++ or other "signals and slots" frameworks.
Your code is definitely preferable. void*
loses any pretense to type safety, your typesafe overloads are much better. Good instincts.
To support more types generically in C++ you would define a class or function template, not use void*
. References would be preferable to pointers, but your code could be changed to this:
template <class T> T increase(T* value)
{
return ++(*value);
}
int main(int argc, char* argv[])
{
int i(0);
increase<int>(&i);
char c(0);
increase<char>(&c);
return 0;
}
What's the website, as a matter of interest?
精彩评论