Pointer, Class and void* in C++
I get a code for Fibonacci Heap. This code uses the follow function to compare two keys:
int
cmp(void *x, void *y)
{
int a, b;
a = (int)x;
b = (int)y;
if (a < b)
return -1;
if (a == b)
return 0;
return 1;
}
This works because the KEY is currently a INT number.
I would like to adapt this code to use my class called "Node". This class have implemented the operator <. >, <=, == and >=.
My adaptation in the code was:
Node a, b // instead int a, b
a = (Node)x;
b = (Node)y;
But I get the error:
dijkstra.cpp:168: error: no matching function for call to 'Node::Node(void*&)'
graph.h:39: note: candidates are: Node::Node()
graph.h:39: note: Node::Node(const Node&)
I tried also:
Node a, b // instead int a, b
a = (Node*)x;
b = (Node*)y;
and get the error:
dijkstra.cpp:168: error: no match for 'operator=' in 'a = (Node*)x'
graph.h:39: note: candidates are: Node& Node::operator=(const Node&)
开发者_C百科I give up to try set the value and solve the question as a follow:
int cmp(void *x, void *y)
{
if ((Node*)x < (Node*)y)
return -1;
if ((Node*)x == (Node*)x)
return 0;
return 1;
}
I would like to understand what I am doing wrong in the previous examples.
Thanks in advance.
Change the following lines
a = (Node*)x;
b = (Node*)y;
to
a = *( (Node*) x);
// type cast from void* to Node* and then fetch the contents by dereferencing the pointer.
b = *( (Node*) y);
You were merely type casting the pointers from void*
to Node*
and trying to assign the pointer to a variable of type Node
.
You said you overloaded operators(<,==,etc..) for the Node class. But the function compares pointers as is. You need to dereference them in order to use your operators. Try this:
int
cmp(void *x, void *y)
{
Node *a, *b;
a = (Node*)x;
b = (Node*)y;
if (*a < *b)
return -1;
if (*a == *b)
return 0;
return 1;
}
Looks like you are calling the cmp
function (or it is getting called via a callback) with a reference to the Node object. If that is the case you can change your code to
Node& a = static_cast<Node&>(*x);
Node& b = static_cast<Node&>(*y);
I am guessing this without looking at the calling code - which, honestly is not a good idea. If you can post the calling code too, it will be helpful to answer the question better.
There no reason to compare (Node*) or (void*) values - this is just pointers and you will compare memory addresses. It looks like all you need to make first example work is implement operator =
.
Adding to what yasouser said, your first program will not work as expected.
a = *(int*)x; b = *(int*)y;
First about your cmp function itself:
usually people only implement operator<
; when operator>
is implemented, it is usually through a call to the already implemented operator<
with reversed parameters. Your implementation of cmp also requires the Node implement operator==
, which might be unnecessary.
Also, there is a small issue if your function accepts void* but internally converts them to NODE* and dereferences them AND it yet it is named with a generic "cmp".
A better implementation would be this:
int NodeCmp(void *x, void *y)
{
// handle NULL pointers here
if (*(Node*)x < *(Node*)y)
return -1;
if (*(Node*)y < *(Node*)x)
return 1;
return 0;
}
If you're feeling up to it, you might want to look into std::less or template functions.
Typically when you are passing a void*
to a function, you must then cast the pointer to another pointer of the type you are wanting. For example:
void func(void* a, void* b)
{
int* c, d;
c = (int*)a;
d = (int*)b;
//... continue rest of function
}
You on the otherhand are trying to value initialize an object of type T
when you write
(T)value;
or
T(value);
That is why you're getting complaints about not having a proper constructor type for the object of type T
.
What you should be doing is casting to a pointer of type T*
, and then dereferencing those new casted pointers to-do whatever comparisons you want between the actual objects of type T
. For example (assume T
is some desired type you want to compare ... i.e., this is not a template):
int cmp(void* a, void* b)
{
T* c, d;
c = (T*)a;
d = (T*)b;
if (*c < *d)
return -1;
else if (*c > *d)
return 1;
else
return 0;
}
精彩评论