qobject_cast and dynamic cast fail, while static_cast seems to work
-
I have a class
ClientSslSocket
that is derived fromQSslSocket
and has theQ_OBJECT
macro:class ClientSslSocket : public QSslSocket { Q_OBJECT ... };
Somewhere in a method of another class
FooBar
, thedisconnected()
signal of this class is connected to thedisconnectedCallback()
slot inFooBar
:bool FooBar::initializeSocket(ClientSslSocket* socket) { ... connect(socket, SIGNAL(disconnected()), this, SLOT(disconnectedCallback())); .... }
In the
disconnectedCallback()
slot, I noticed thatdynamic_cast
andqobject_cast
did not work, butstatic_cast
does seem to work as expected:ClientSslSocket* sender1 = dynamic_cast<ClientSslSocket*>(sender()); // returns 0 ClientSslSocket* sender2 = qobject_cast<ClientSslSocket*>(sender()); // returns 0 ClientSslSocket* sender3 = static_cast<ClientSslSocket*>(sender()); // seems to work...
I don't understand or see why
qobject_cast
anddynamic_cast
return 0 here, indicating that the qobject/dynamic cast didn't succeed... although this looks like a simple signal-slot connection. What am I overlooking here, or what should I look for to diagnose this any further?Kind regards,
Bart -
Add
qDebug() << sender()
. What do you see? -
Hi Bart,
qobject_cast should work as long as everything is QObject inherited. I've tested your code and
SlientSslSocket* sender2 = qobject_cast<SlientSslSocket*>(sender());
and it's working (qt 5.5, gcc 4.8.4). I thing there might be problem how is your socket for the method initializeSocket(ClientSslSocket* socket) created. Could you paste longer example? -
@JKSH said:
Add
qDebug() << sender()
. What do you see?This gives me
QSslSocket(0x4b1e370)
I do not understand why I have a
QSslSocket
here. I am expecting a `ClientSslSocket' object, because basically, the structure of the code is as follows (I cannot literally copy-paste due to company restrictions):bool Foo::initializeSocket(ClientSslSocket* socket) { .... connect(socket, SIGNAL(disconnected()), this, SLOT(disconnectedCallback())); .... }
If I go up one level in the call stack, then I see that the initializeSocket function gets called as follows:
ClientSslSocket* socket = new ClientSslSocket(); if ( initializeSocket(socket)== true ) { ... }
so for as far as I can see, it gets a pointer to a
ClientSslSocket
object... I'm puzzled and don't see what I'm overlooking. Could it be something in the implementation ofClientSslSocket
that I'm forgetting? -
-
After some more debugging, I think I figured out the problem. It turns out that the
FooBar
class has another data structure which also holds pointers toClientSslSocket
s, andFooBar
's destructor looks as follows:FooBar::~FooBar() { for (int i = 0; i < theList.size(); ++i) { if (theList.at(i).socket) { #ifdef linux theList.at(i).socket->close(); #else delete TheList.at(i).mpSocket; #endif mvConnectionInfoList.at(i).mpSocket = NULL; } } }
I'm on Windows, and from what I can debug right now, it seems that the line
delete TheList.at(i).mpSocket;
is causing the
ClientSslSocket
destructor being called. And apparently, that samedelete
statement also triggers thedisconnect()
signal so that thedisconnectedCallback()
slot is called, apparently with an already partly destructed sender object (that is my educated guess, I found out that theClientSslSocket
destructor is called before the slot is handled...).So I have some more questions now:
- Could my educated guess be correct?
- Does anybody have any idea why the original author of this code decided to make a difference between linux and non-linux? If I remove the
ifdef
and simply useclose()
in all situations, things seem to work, although it seems that in this case theClientSslSocket
destructor is no longer called (and I'm not sure if this is a good thing...). - What would be the clean solution here? How should FooBar's destructor look like?
Thanks for bearing with me ;-)
Bart -
@Bart_Vandewoestyne said:
- Could my educated guess be correct?
Your guess sounds reasonable to me.
- Does anybody have any idea why the original author of this code decided to make a difference between linux and non-linux? If I remove the
ifdef
and simply useclose()
in all situations, things seem to work, although it seems that in this case theClientSslSocket
destructor is no longer called (and I'm not sure if this is a good thing...).
Nope, sorry. Are there any comments in the code, or in the commit history? Could you ask the author directly?
- What would be the clean solution here? How should FooBar's destructor look like?
It's hard to say without knowing how the rest of the program is designed. Maybe you can manually disconnect the socket before deleting it?