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 to
QWidget
? -
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.
Best Answer
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 ofNetworkTools
at all. It can be a plain member ofNetworkTools
. It’s tied to the lifetime ofNetworkTools
anyway and you’d avoid any special work in the ctor or dtor as well as a bunch of pointer indirections when accessing theview
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 Linuxsizeof(QWebEngineView) == 56
. That’s not super tiny, but nothing to worry about. For comparison:sizeof(QString) == 8
andsizeof(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:For everything else I’d default to
std::unique_ptr
orstd::shared_ptr
for the few special cases where you have real shared ownership.