C++ 将信号和插槽附加到QSharedPointer内的对象

C++ 将信号和插槽附加到QSharedPointer内的对象,c++,qt,qsharedpointer,C++,Qt,Qsharedpointer,我的应用程序包含以下几个功能: void SomeClass::set_data_provider(DataProvider *data_provider) { connect(data_provider, SIGNAL(data_available(int)), this, SLOT(data_available(int))); } QSharedPointer<MyObject> shared(new MyObject); my_connect(shar

我的应用程序包含以下几个功能:

void SomeClass::set_data_provider(DataProvider *data_provider)
{
    connect(data_provider, SIGNAL(data_available(int)),
        this, SLOT(data_available(int)));
}
QSharedPointer<MyObject> shared(new MyObject);
my_connect(shared, SIGNAL(my_signal()), this, SLOT(my_slot()));
为了避免传递原始指针,我将所有出现的
DataProvider*
更改为
QSharedPointer
。后者几乎是前者的替代品,只是您不能将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)));
}
void SomeClass::set_data_provider(QSharedPointer data_provider)
{
连接(data_provider.data(),信号(data_available(int)),
这个插槽(数据_可用(int));
}

这看起来很好,但看起来不雅观,我对这样访问原始指针很谨慎。有没有更好的方法连接到QSharedPointer中传递的对象?

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

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);
}
模板bool
my_connect(常量QSharedPointer和sender,
常量字符*信号,
常量QObject*接收器,
常量字符*方法,
Qt::ConnectionType类型=Qt::自动连接)
{
返回QObject::connect(sender.data(),信号,接收器,方法,类型);
}
然后像这样使用它:

void SomeClass::set_data_provider(DataProvider *data_provider)
{
    connect(data_provider, SIGNAL(data_available(int)),
        this, SLOT(data_available(int)));
}
QSharedPointer<MyObject> shared(new MyObject);
my_connect(shared, SIGNAL(my_signal()), this, SLOT(my_slot()));
QSharedPointer共享(新的MyObject);
my_connect(共享,信号(my_SIGNAL()),此,插槽(my_插槽());
唯一的问题是,在您和我的解决方案中,您将丢失本机连接函数的Qt Creator autocomplete


对我来说,我不会改变你的密码。我认为这很好:)

为了完整起见,这里是@hank答案的扩展。我提供了六种类似“连接”的功能:

  • connect\u from_pointer
    将QSharedPointer作为其第一个参数,将通常的
    QObject*
    作为其第三个参数
  • connect_to_pointer
    将通常的
    QObject*
    作为其第一个参数,将QSharedPointer作为其第三个参数
  • connect_指针
    为这两个参数都使用qsharedpointer
每种类型都有两个版本:一个接受
信号()
/
插槽()
语法,另一个接受(推荐的)函数指针

这些在语法上很糟糕,但这只是你的模板

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);
}
模板
QMetaObject::连接从\u指针连接\u(
常量QSharedPointer和sender,
常量字符*信号,
常量QObject*接收器,
常量字符*方法,
Qt::ConnectionType类型=Qt::自动连接)
{
返回QObject::connect(sender.data(),信号,接收器,方法,类型);
}
模板
QMetaObject::连接从\u指针连接\u(
常量QSharedPointer和sender,
Func1信号,
常量typename QtPrivate::FunctionPointer::Object*接收器,
功能2插槽,
Qt::ConnectionType类型=Qt::自动连接)
{
返回QObject::connect(sender.data(),信号,接收器,插槽,类型);
}
模板
QMetaObject::连接连接\u到\u指针(
常量QObject*发送方,
常量字符*信号,
常数QSharedPointer和receiver,
常量字符*方法,
Qt::ConnectionType类型=Qt::自动连接)
{
返回QObject::connect(发送方、信号、接收方.data()、方法、类型);
}
模板
QMetaObject::连接连接\u到\u指针(
常量typename QtPrivate::FunctionPointer::Object*发送方,
Func1信号,
常数QSharedPointer和receiver,
功能2插槽,
Qt::ConnectionType类型=Qt::自动连接)
{
返回QObject::connect(发送器、信号、接收器.data()、插槽、类型);
}
模板
QMetaObject::连接\u指针(
常量QSharedPointer和sender,
常量字符*信号,
常数QSharedPointer和receiver,
常量字符*方法,
Qt::ConnectionType类型=Qt::自动连接)
{
返回QObject::connect(sender.data(),signal,receiver.data(),method,type);
}
模板
QMetaObject::连接\u指针(
常量QSharedPointer和sender,
Func1信号,
常数QSharedPointer和receiver,
功能2插槽,
Qt::ConnectionType类型=Qt::自动连接)
{
返回QObject::connect(sender.data(),signal,receiver.data(),slot,type);
}

这很有趣,我不知道你能做到。然而,我不认为它改进了原来的。使用QMetaData/qRegisterMetaType要整洁得多,因为这正是该机制的原因:),再加上您还可以保持自动完成:))我想OP没有询问如何通过信号槽机制发送
QSharedPointer
对象(在这种情况下,确实应该使用
qRegisterMetaType
)但是如何将
QSharedPointer
对象传递给
connect
函数。但是“如何通过信号槽发送QSharedPointer”和“如何将QSharedPointer对象传递给connect函数”。。。。基本上是一样的,因为connect是信号槽机制的一部分。但无论如何,我很喜欢你所做的,这是开箱即用的,但我只是指出这不是最好的方式(也许只是在我看来)。没有lambda love?