开发者

Pointer, Class and void* in C++

开发者 https://www.devze.com 2023-03-07 01:10 出处:网络
I get a code for Fibonacci Heap. This code uses the follow function to compare two keys: int cmp(void *x, void *y)

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;
}
0

精彩评论

暂无评论...
验证码 换一张
取 消