c++qtupcastingqpointer

How to upcast `QPointer<descendant>`


I have declared a class B, and a descendant class D. I also have a method:

myMethod(QPointer<B> param1) {}

When I try to call myMethod() with a QPointer to D as the parameter, the compiler complains that:

cannot convert 'QPointer<D>' to 'QPointer<B>'

Why is it complaining? I thought passing a QPointer<D> will implicitly upcast it to QPointer<B>. How should I resolve this?


Solution

  • QPointer<T> is a guarded pointer where T must be derived from QObject (see here). "Guarded" here just means that it can be either nullptr or pointing at legal QObject, i.e. an object which wasn't destroyed yet, no reference counting involved, a framework state is used.

    Since Qt 6.6 there are defined constructors which facilitate cast

    template <typename X, QPointer<T>::if_convertible<X> = true> 
    QPointer::QPointer(QPointer<X> &&other)
    
    template <typename X, QPointer<T>::if_convertible<X> = true> 
    QPointer::QPointer(const QPointer<X> &other)
    

    If that doesn't happen, it means your X isn't convertible to T, e.g. isn't related or you somehow used multiple inheritance, etc. In general case a cast to QPointer<QObject> always should work, multiple or virtual inheritances from QObject aren't supported by Qt.

    In most cases argument defined as QPointer<B> param1 is a useless waste of time to cast and copy pointer wrappers, for single thread it can be abolished and internal qobject_cast or Qt test macros can be used. There is no real guarantee that object wasn't destroyed and a new object of same type was created in place, afaik, all it guarantees that pointer contains a "correct", safe-to-dereference value. For multi-threaded uses sometimes you may need a ref-counting owning pointer QSharedPointer.