qobject_cast and dynamic cast fail, while static_cast seems to work



  • I have a class ClientSslSocket that is derived from QSslSocket and has the Q_OBJECT macro:

    class ClientSslSocket : public QSslSocket
    {
        Q_OBJECT
        ...
    };
    

    Somewhere in a method of another class FooBar, the disconnected() signal of this class is connected to the disconnectedCallback() slot in FooBar:

    bool FooBar::initializeSocket(ClientSslSocket* socket)
    {
        ...
        connect(socket, SIGNAL(disconnected()), this, SLOT(disconnectedCallback()));
        ....
    }
    

    In the disconnectedCallback() slot, I noticed that dynamic_cast and qobject_cast did not work, but static_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 and dynamic_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


  • Moderators

    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 of ClientSslSocket that I'm forgetting?



  • @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 FooBar class has another data structure which also holds pointers to ClientSslSockets, and FooBar'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 same delete statement also triggers the disconnect() signal so that the disconnectedCallback() slot is called, apparently with an already partly destructed sender object (that is my educated guess, I found out that the ClientSslSocket destructor is called before the slot is handled...).

    So I have some more questions now:

    1. Could my educated guess be correct?
    2. 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 use close() in all situations, things seem to work, although it seems that in this case the ClientSslSocket destructor is no longer called (and I'm not sure if this is a good thing...).
    3. What would be the clean solution here? How should FooBar's destructor look like?

    Thanks for bearing with me ;-)
    Bart


  • Moderators

    @Bart_Vandewoestyne said:

    1. Could my educated guess be correct?

    Your guess sounds reasonable to me.

    1. 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 use close() in all situations, things seem to work, although it seems that in this case the ClientSslSocket 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?

    1. 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?



Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.