将QObject用作类成员并将该成员用作连接上下文是否安全?

时间:2019-07-11 23:11:17

标签: c++ qt c++11 qt5

我有一个“普通”(非qt派生)类。它正在传递一个QObject引用。在此类中,我想将输入的QObject信号与lambda连接。 到目前为止,一切正常,除非在传递给QObject之前销毁了我的类的对象。现在,来自QObject的信号指向的lambda不再存在。

通常的做法是,我的类继承自QObject,并将this作为上下文传递给connect。我的对象死亡后,连接将被Qt代码自动破坏。

解决此问题的另一种方法是保存connect的返回结果,即QMetaObject::Connection,然后保存在我的类调用QObject::disconnect(resultOfConnect)的析构函数中。

现在我想解决的方式是这样的:

class SomeQtDerivedClass : public QObject {...}

class MyClass
{
public:
    MyClass(SomeQtDerivedClass& qtObject)
    {
        connect(&qtObject, &qtObject::someSignal, &m_QtObject, [](){blahblah})
    }
private:
    QObject m_QtObject;
}

我没有在任何地方使用过这种模式,而且在官方文档中也找不到关于这种方法的任何东西。如果可以改用合成,我不想从QObject继承。如果可以在堆栈上创建m_QtObject,我不想在其上创建。而且,如果我的类对象在输入的QObject之前被销毁,我希望自动销毁连接。

这项工作可以吗?

2 个答案:

答案 0 :(得分:4)

它应该可以正常工作(当然,只要您没有在m_QtObject上设置父对象); m_QtObject与您的类一起被销毁(在用户提供的析构函数之后,如果有的话),因此它与您从QObject派生的几乎没有什么不同(实际上,从许多角度来看,基类都非常相似)给隐藏的头等舱成员)。

话虽这么说,我会使用QMetaObject::Connection(可能将其包装到std::unique_ptr中,或在破坏时自动断开连接); QObject的重量很重,仅使用它来利用其自动断开连接功能似乎有点浪费。

答案 1 :(得分:2)

这不是问题的直接答案,但它回答了@vuko_zrno的误解。

拥有QObject作为成员(反对QObject *)不能保证您进行堆栈分配。它仅向您保证QObject将使用与拥有它的MyClass实例相同的内存块。

例如,如果您执行MyClass obj;,则MyClass和QObject都将在堆栈上。但是如果您执行MyClass * obj = new MyClass;,它们都将处于堆中。

Qt类也很重要,它大量使用了pimpl设计模式。这意味着QObject类只是一个空壳,其所有成员变量都存储在另一个名为QObjectPrivate的类中。

实际上,QObject的大小在64位上为16个字节,而QObjectPrivate的大小为112个字节。并且QObjectPrivate将始终分配在堆上。

因此在实践中,我不确定QObjectQObject *会有什么有意义的区别。