[Interest] Qt signals and polymorphism
Bob Hood
bhood2 at comcast.net
Sun Nov 22 18:21:45 CET 2015
I successfully addressed my QMutex/QWaitCondition breakage by refactoring my
termination chain. By sending a 'last call' down my class hierarchy, I was
able to give the threads the time they needed to actually end gracefully, and
release their resources.
However, while implementing this, I did discover that Qt signals cannot be
virtualized, and I wanted to just confirm that in certain circumstances (mine
in particular), they can actually mess with OOD. Let me explain.
Given a class Channel:
class Channel : public QObject
{
...
Channel();
signals:
void signal_channel_clear();
...
}
and given a class Client that contains a class Channel:
class Client : public QObject
{
...
Client(QSharedPointer<Channel> channel_pointer);
signals:
void signal_client_clear();
protected slots:
void slot_channel_clear(); // to receive Channel::signal_channel_clear
...
}
then given a subclass of Channel:
class SubChannel : public Channel
{
...
SubChannel();
signals:
void signal_channel_clear();
...
}
If I connect Channel::signal_channel_clear() to Client::slot_channel_clear()
when Client is passed a Channel pointer of type SubChannel:
connect(channel_pointer.data(), &Channel::signal_channel_clear, this,
&Client::slot_channel_clear);
then Client will never receive the signal when it is emitted from the
SubChannel class (because it was bound to Channel::signal_channel_clear).
Instead, from what I can fathom, I have to either dynamically cast SubChannel
within Client (very ugly, because Client doesn't know about SubChannel and may
not even have access to its header), or I have to make the Client slot public,
and at a level above them all, make the connections on their behalf,
increasing the coupling level:
QSharedPointer<SubChannel> subchannel = QSharedPointer(new SubChannel());
QSharedPointer<Client> client = QSharedPointer(new Client(subchannel));
connect(client.data(), &Client::slot_channel_clear, subchannel.data(),
&SubChannel::signal_channel_clear);
Basically, then, I wanted to know if this was the proper/only way to achieve
this, of if there was something obvious I'm overlooking? Both approaches are
somewhat ugly, but the latter is (for me) the lesser of the two evils.
More information about the Interest
mailing list