3

I'm using QT 5.7 and, because of the libraries I have to use, I need to convert a QObject ('s derived class) to and from a void pointer.

A couple of definitions. I have a function that accepts only a void pointer, and my class derives from QObject:

void oneFunction(void *obj);

class MyObj : public QObject
{
    ...
};

Then I create and fill an object:

MyObj *ptr = new MyObj(parent);
ptr->.......

At some point I convert it to a void pointer, because I have to pass it to the function. This cast is done automatically:

oneFunction(ptr);

Then, after some time, I receive back the pointer I passed, and I need to convert it back to the original class. The pointer was not modified by the function:

void callbackFromOneFunction(void *theOldPointer)
{
    MyObj *oldPtr = qobject_cast<MyObj*>(static_cast<QObject*>(theOldPointer));
    if (oldPtr != nullptr)
    {
        ... Now it's back, so use it
    }
}

Now, is this whole procedure right? Is there some problem/leak you spot? Is there a better solution?

Thank you

frarugi87
  • 2,826
  • 1
  • 20
  • 41
  • 1
    If you convert from `MyObj*` to `void*` with an implicit conversion, you need to `static_cast` back to `MyObj*`, not to `QObject*`. Round-tripping is only guaranteed if the types are exactly the same. – Sebastian Redl Sep 20 '16 at 11:26

2 Answers2

6

I think a single static_cast is enough.

static_cast doesn't check the type at runtime and should be used when you're sure the type is okay. In this case you're sure, and you won't need qobject_cast. qobject_cast checks the type at runtime (it's similar to dynamic_cast).


In case of target type being known

A static_cast or C-style cast is okay. Although C-style cast works fine here, it's not recommended because:

  • C-style casts are't checked by compiler whereas static_casts are.
  • static_casts are far more readable and can be searched for more easily.
  • More info.

In case of target type being unknown

  • When the source type is QObject * or its derivations, a single qobject_cast is enough.

  • If the source type is polymorphic, dynamic_cast is used. In other words, dynamic_cast is used only for polymorphic source types (i.e. classes having at least one virtual function). In such classes, at compile-time we can't determine the most derived type of pointers which point to base classes having virtual methods, only at runtime we can determine them.

    About dynamic casting void*, it's allowed to cast to but not cast from.

In your case void* doesn't have any RTTI, so neither qobject_cast nor dynamic_cast can be used.

Community
  • 1
  • 1
frogatto
  • 28,539
  • 11
  • 83
  • 129
  • The problem with solution 2 (only `qobject_cast`) is that `qobject_cast` expects a `QObject*`, not a `void*`, so a single one is not enough – frarugi87 Sep 20 '16 at 12:56
  • C-style cast should be avoided. – rubenvb Sep 20 '16 at 13:45
  • @rubenvb You're right. `static_cast` is preferable over C-style cast for sake of readability and being checked by compiler. updated my answer. – frogatto Sep 20 '16 at 14:01
  • They're also not equivalent: a C style cast is still radically different from any c++ cast, see [this answer](http://stackoverflow.com/a/332086/256138). – rubenvb Sep 20 '16 at 14:22
  • @rubenvb I didn't say they are equivalent. I said both casts work, even through it's highly recommended to not use C-style cast in C++. – frogatto Sep 20 '16 at 19:09
3

If and only if you are certain the pointer was not and will never be touched by oneFunction(void*) in ways that are Undefined, then its safe to cast receive that pointer elsewhere in your program and type-cast it back to QObject. See this.

In that case, this is perfectly valid:

void callbackFromOneFunction(void *theOldPointer)
{
    MyObj *oldPtr = qobject_cast<MyObj*>(static_cast<QObject*>(theOldPointer));
    if (oldPtr != nullptr)
    {
        ... Now it's back, so use it
    }
}
Community
  • 1
  • 1
WhiZTiM
  • 21,207
  • 4
  • 43
  • 68