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:
Is it true that Qt6 plans on letting
QObject
serve as a parent toQWidget
?Is my destructor method done right, and is it a safe strategy in preventing memory leaks?
Is there a safer practice available?
Should I be utilizing any of Qts smart pointers instead:
Thanks.
2 Answers 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.
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.
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.
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.
Explore related questions
See similar questions with these tags.
view
have to be any kind of pointer?