Присоединение сигналов и слотов к объекту внутри QSharedPointer

Мое приложение содержало несколько таких функций:

void SomeClass::set_data_provider(DataProvider *data_provider)
{
    connect(data_provider, SIGNAL(data_available(int)),
        this, SLOT(data_available(int)));
}

Чтобы избежать передачи необработанных указателей, я изменил все вхождения DataProvider * в QSharedPointer<DataProvider>, Последний является почти полной заменой первого, за исключением того, что вы не можете передать QSharedPointer в QObject::connect, Я работал над этим, извлекая необработанный указатель из QSharedPointer:

void SomeClass::set_data_provider(QSharedPointer<DataProvider> data_provider)
{
    connect(data_provider.data(), SIGNAL(data_available(int)),
        this, SLOT(data_available(int)));
}

Кажется, это работает нормально, но выглядит не элегантно, и я опасаюсь обращаться к необработанному указателю, как это. Есть ли лучший способ подключения к объекту, который передается в QSharedPointer?

2 ответа

Решение

Вы можете создать пользовательскую функцию подключения:

template<class T> bool
my_connect(const QSharedPointer<T> &sender,
           const char *signal,
           const QObject *receiver,
           const char *method,
           Qt::ConnectionType type = Qt::AutoConnection)
{
    return QObject::connect(sender.data(), signal, receiver, method, type);
}

И используйте это так:

QSharedPointer<MyObject> shared(new MyObject);
my_connect(shared, SIGNAL(my_signal()), this, SLOT(my_slot()));

Единственная проблема заключается в том, что как в вашем, так и в моем решениях вы потеряете автозаполнение Qt Creator для встроенной функции соединения.

PS Что касается меня, я бы не стал менять твой код. Я думаю, что это нормально:)

Для полноты вот расширение ответа @hank. Я даю шесть connect-подобные функции:

  • connect_from_pointer принимает QSharedPointer в качестве первого аргумента и обычного QObject * в качестве третьего аргумента.
  • connect_to_pointer берет обычное QObject * в качестве первого аргумента и QSharedPointer в качестве третьего аргумента.
  • connect_pointers принимает QSharedPointers для обоих параметров.

Есть две версии каждого из них: один, который принимает SIGNAL()/SLOT() синтаксис и тот, который принимает (рекомендуемые) указатели на функции.

Это синтаксически ужасно, но это шаблоны для вас.

template<class T>
QMetaObject::Connection connect_from_pointer(
    const QSharedPointer<T>& sender,
    const char *signal,
    const QObject *receiver,
    const char *method,
    Qt::ConnectionType type = Qt::AutoConnection)
{
    return QObject::connect(sender.data(), signal, receiver, method, type);
}

template <typename Func1, typename Func2>
QMetaObject::Connection connect_from_pointer(
    const QSharedPointer<typename QtPrivate::FunctionPointer<Func1>::Object>& sender,
    Func1 signal,
    const typename QtPrivate::FunctionPointer<Func2>::Object *receiver,
    Func2 slot,
    Qt::ConnectionType type = Qt::AutoConnection)
{
    return QObject::connect(sender.data(), signal, receiver, slot, type);
}

template<class T>
QMetaObject::Connection connect_to_pointer(
    const QObject *sender,
    const char *signal,
    const QSharedPointer<T>& receiver,
    const char *method,
    Qt::ConnectionType type = Qt::AutoConnection)
{
    return QObject::connect(sender, signal, receiver.data(), method, type);
}

template <typename Func1, typename Func2>
QMetaObject::Connection connect_to_pointer(
    const typename QtPrivate::FunctionPointer<Func1>::Object *sender,
    Func1 signal,
    const QSharedPointer<typename QtPrivate::FunctionPointer<Func2>::Object>& receiver,
    Func2 slot,
    Qt::ConnectionType type = Qt::AutoConnection)
{
    return QObject::connect(sender, signal, receiver.data(), slot, type);
}

template<class T, class U>
QMetaObject::Connection connect_pointers(
    const QSharedPointer<T>& sender,
    const char *signal,
    const QSharedPointer<U>& receiver,
    const char *method,
    Qt::ConnectionType type = Qt::AutoConnection)
{
    return QObject::connect(sender.data(), signal, receiver.data(), method, type);
}

template <typename Func1, typename Func2>
QMetaObject::Connection connect_pointers(
    const QSharedPointer<typename QtPrivate::FunctionPointer<Func1>::Object>& sender,
    Func1 signal,
    const QSharedPointer<typename QtPrivate::FunctionPointer<Func2>::Object>& receiver,
    Func2 slot,
    Qt::ConnectionType type = Qt::AutoConnection)
{
    return QObject::connect(sender.data(), signal, receiver.data(), slot, type);
}
Другие вопросы по тегам