0

Consider the following constructor:

NetworkTools::NetworkTools(QObject *parent) : QObject(parent)
{
    view = new QWebEngineView();
    view->setParent(parent); // Produces an error, shown below.
}

While QWebEngineView is a QWidget, it is able to be utilized without ever having to open a widget window, using:

void QWebEngineView::load(const QUrl &url)

in place of

void QWidget::show()

As such, I will be integrating it into various QObject based console applications. The issue however is setting parents. The code above produces this error:

error: invalid conversion from ‘QObject*’ to ‘QWidget*’ [-fpermissive]
view = new QWebEngineView(parent);
                                ^

According to this answer on SO,

Qt is not designed to support a non-widget parent to a QWidget

but then states later:

It's not a worthwhile fight, I think - not unless a decision is made to make a QWidget truly-a QObject and change its constructor signature. That can be done at the earliest in Qt 6 since it's a binary-incompatible change AFAIK.

It is suggested that casting the parent will just lead to issues, so my solution is just making sure all my QWidget pointers belong to a class, and to simply delete them in the class destructor like so:

NetworkTools::~NetworkTools() {delete view;}

Compromising the setParent functionality. I am not even sure if that is the proper way to delete a QWidget pointer. As such:

  1. Is it true that Qt6 plans on letting QObject serve as a parent to QWidget?

  2. Is my destructor method done right, and is it a safe strategy in preventing memory leaks?

  3. Is there a safer practice available?

  4. Should I be utilizing any of Qts smart pointers instead:

Thanks.

  • I smurfing hate smurf prefixes. – candied_orange Apr 10 '18 at 20:40
  • @CandiedOrange hmmmmm pointer lifespan? – Akiva Apr 10 '18 at 21:41
  • 1
    Why does view have to be any kind of pointer? – Caleth Apr 11 '18 at 8:33
2

1.

Your linked SO answer just talks about the earliest possible point where such a change could occur. Personally I’ve never seen a proposal or discussion about actually doing something like that.

2. to 4.

tl;dr: Sidestep the problem and make the view a plain member of NetworkTools.

Longer answer: Your approach uses RAII, which is the preferred way to handle ownership in C++. That’s perfectly valid, but it’s not ideal in this case.

From your question I can’t see a reason why you should allocate the QWebEngineView outside of NetworkTools at all. It can be a plain member of NetworkTools. It’s tied to the lifetime of NetworkTools anyway and you’d avoid any special work in the ctor or dtor as well as a bunch of pointer indirections when accessing the view member.

You might want to allocate the view separately if it is huge and you want to allocate (lots of) NetworkTools objects on the stack – although that seems unlikely. With huge objects, running out of stack space is a real possibility. However, on my Qt 5.10 64bit Linux sizeof(QWebEngineView) == 56. That’s not super tiny, but nothing to worry about. For comparison: sizeof(QString) == 8 and sizeof(QObject) == 16.

If you really absolutely have to allocate the view separately, prefer std::unique_ptr for the simple reason that it is the default single-ownership smart pointer provided by the C++ standard library itself. Qt’s smart pointers mostly originate in ancient times when C++ didn’t have any smart pointers. There are two situations where I’d consider a Qt smart pointer:

  • If I wanted to tap into Qt’s implicit-sharing/copy-on-write system. That’s what the SharedData pointers are for.
  • To avoid needless conversions if I had to use a part of Qt’s API that requires a Qt smart pointer.

For everything else I’d default to std::unique_ptr or std::shared_ptr for the few special cases where you have real shared ownership.

1
  1. I doubt it. I think what they meant is that if that change will every be made to QWidget, it won't be made before Qt6, because it's breaking binary compatibility, but it's not to be assumed it will be made.

  2. I don't know your code, but in general Qt destroys automatically all childrens, i.e. widgets with a parent, when the parent is destroyed. Thus you only have to destroy widgets without a parent.

  3. and 4. Imho yes, using smart pointers is safer, because it becomes much harder to mis-handle destruction (forgetting the destruction, or destroying multiple times). As a general guideline, if you are not sharing your pointers between multiple users, use a QScopedPointer, otherwise use a QSharedPointer. The others are more specialized versions. You can also use boost or C++11 scoped_ptr and shared_ptr.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.