qobject_cast and dynamic cast fail, while static_cast seems to work
-
I have a class
ClientSslSocketthat is derived fromQSslSocketand has theQ_OBJECTmacro: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_castandqobject_castdid not work, butstatic_castdoes 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_castanddynamic_castreturn 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
QSslSockethere. 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
ClientSslSocketobject... I'm puzzled and don't see what I'm overlooking. Could it be something in the implementation ofClientSslSocketthat I'm forgetting? -
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?@yeckel Do you have the code of your test-program available somewhere? I would like to test it on my platform...
-
@yeckel Do you have the code of your test-program available somewhere? I would like to test it on my platform...
-
After some more debugging, I think I figured out the problem. It turns out that the
FooBarclass has another data structure which also holds pointers toClientSslSockets, 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
ClientSslSocketdestructor being called. And apparently, that samedeletestatement 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 theClientSslSocketdestructor 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
ifdefand simply useclose()in all situations, things seem to work, although it seems that in this case theClientSslSocketdestructor 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 -
After some more debugging, I think I figured out the problem. It turns out that the
FooBarclass has another data structure which also holds pointers toClientSslSockets, 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
ClientSslSocketdestructor being called. And apparently, that samedeletestatement 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 theClientSslSocketdestructor 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
ifdefand simply useclose()in all situations, things seem to work, although it seems that in this case theClientSslSocketdestructor 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
ifdefand simply useclose()in all situations, things seem to work, although it seems that in this case theClientSslSocketdestructor 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?