【问题标题】:Attaching signals and slots to an object within a QSharedPointer将信号和槽附加到 QSharedPointer 中的对象
【发布时间】:2015-10-22 23:04:21
【问题描述】:

我的应用程序包含几个这样的函数:

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 中传递的对象?

【问题讨论】:

    标签: c++ qt qsharedpointer


    【解决方案1】:

    您可以创建自定义连接函数:

    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 自动完成功能。

    附:至于我,我不会更改您的代码。我觉得挺好的:)

    【讨论】:

    • 这很有趣,我不知道你能做到这一点。但是,我认为它并没有改善原版。使用 QMetaData / qRegisterMetaType 更整洁,因为这正是机制的原因:),另外你也保持你的自动完成:))
    • 我想 OP 不是询问如何通过信号槽机制发送QSharedPointer 对象(在这种情况下确实应该使用qRegisterMetaType),而是如何将QSharedPointer 对象传递给connect 函数。
    • 但是“如何通过信号槽发送 QSharedPointer”和“如何将 QSharedPointer 对象传递给连接函数”......基本上是一样的,因为连接是信号槽的一部分机制。但无论如何,我很喜欢你所做的,它在盒子外面,但我只是指出这不是最好的方法(也许只是在我看来)。
    【解决方案2】:

    为了完整起见,这里是@hank 答案的扩展。我提供了六个connect-like 函数:

    • 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);
    }
    

    【讨论】:

    • 没有 lambda 爱?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-02-25
    • 1970-01-01
    • 2019-12-04
    • 2021-08-28
    • 1970-01-01
    • 2019-04-15
    • 1970-01-01
    相关资源
    最近更新 更多