Qt disconnectNotify () не вызывается при уничтожении объекта-получателя - PullRequest
2 голосов
/ 05 марта 2012

У меня есть класс C, который излучает сигнал S. S может быть подключен к нулю, к одному или нескольким приемникам (R) (количество соединений меняется со временем, а соединения w выполняются приемниками).

C должен что-то делать, когда число слушателей S становится больше нуля, и делать что-то еще, когда число слушателей на S возвращается к нулю.

Я думал, что могу использовать:

connectNotify()

и

disconnectNotify()

ну, ...

Что я замечаю, так это то, что функция connectNotify () работает хорошо, но функция disnectNotify () не вызывается(в классе C), когда принимающий объект уничтожен.Он вызывается только тогда, когда используется явное разъединение с использованием disconnect ().

Добавление явного разъединения в деструкторе слушателей также оказалось не очень успешным: возникла ошибка сегментации при выходе из всего приложения.(Я думаю, что не очень хорошо пытаться использовать метод connect (), когда все идет не так.)

Я пытался использовать сигнал destroy (), отправляемый от экземпляров R к C, когда R уничтожается: Это работает, но как я могу быть уверен, что R был подключен во время уничтожения?(Приемники R могут существовать в неподключенном состоянии):

В классе C слот X (вызываемый при получении destroy () R), проверяя QObject :: receivers (), похоже, возвращает числоприемники до уничтожения не производится.Поскольку я не знаю, был ли объект уничтожен связан, я застрял!

Есть идеи?

1 Ответ

1 голос
/ 05 марта 2012

Если вы можете гарантировать, что все R уничтожены до C, вы можете сами управлять соединениями в классе C:

Заголовочный файл:

#include <QtCore/QSet>

class C : (...)
{
    (...)

public:
    void connectReceiver( QObject* receiver );

private slots:
    void handleReceiverDestruction( QObject* receiver );

private:
    QSet< QObject* > _connectedReceivers;
};

Исходный файл:

void C::connectReceiver( QObject* receiver  )
{
    // nothing to do if the receiver is already connected
    if( _connectedReceivers.contains( receiver  ) ) return;

    _connectedReceivers.append( receiver )

    connect( ... ); // <- do your connection(s) here
    connect( receiver, SIGNAL( destroyed                ( QObject* ) ), 
             this    , SLOT  ( handleReceiverDestruction( QObject* ) ) );
}

void C::handleReceiverDestruction( QObject* receiver )
{
    if( !_connectedReceivers.contains( receiver ) )
    {
        // if this happens, a receiver R's destroyed() signal was connected to
        // this function altough R is not a receiver of signal X.
        Q_ASSERT( false );
        return;
    }

    disconnect( ... ); // <- one or more might be necessary here

    _connectedReceivers.remove( receiver );
}

Подсказка: я не проверял это на компиляцию или логические ошибки, но вы должны понять.

Лично я бы добавил следующее:

C::~C()
{
    if( !_connectedReceivers.isEmpty() )
    {
        // If you land here, a receiver was not (properly) destroyed before this object
        Q_ASSERT( false );
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...