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



我有一个"normal"(非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 之前被销毁,则自动销毁连接。

这行得通吗?

它应该可以正常工作(当然,只要您不设置父级m_QtObject);m_QtObject被你的类销毁(在用户提供的析构函数之后,如果有的话),所以它与你从QObject派生几乎没有什么不同(事实上,从许多角度来看,基类确实类似于隐藏的第一类成员)。

话虽如此,我会使用QMetaObject::Connection(可能将其包装成std::unique_ptr或其他东西,以便在销毁时自动断开连接);QObject是相当重量级的,仅仅使用它来利用其自动断开连接功能似乎有点浪费。

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

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

例如,如果你这样做MyClass obj;那么MyClass和QObject都将在堆栈上。但如果你这样做MyClass * obj = new MyClass;,它们都会堆起来。

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

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

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

相关内容

  • 没有找到相关文章