QObject作为另一个QObject的字段?

时间:2015-10-22 08:50:12

标签: qt qobject

我们通常编写拥有其他QObject的QObject派生类:

class Foo: public QObject {
    Q_OBJECT
public:
    Foo(QObject *parent = nullptr) 
    : QObject(parent), bar(nullptr)
    {
        bar = new Bar(this);
    }
private:
    Bar *bar;
};

但是,在查看同事的代码时,我发现了这种模式:

class Foo: public QObject {
    Q_OBJECT
public:
    Foo(QObject *parent = nullptr) 
    : QObject(parent)
    { }
private:
    Bar bar;
};

它似乎按预期工作,但这样做实际上是安全的,除非有明显的“不要bar->deleteLater()”吗?

4 个答案:

答案 0 :(得分:2)

是的,这是安全的,只要您不尝试删除栏,因为它会在删除Foo后自动释放。

可以说,决定走哪条路取决于实际FooBar是什么。

Bar是一个类的组合时,我更倾向于使用第二种方法。在这种情况下,它是它的一部分,这意味着没有Bar,Foo没有意义。

相反,如果Bar是聚合类,则指向其对象的指针更实用。在这种情况下,Bar是Null,Foo仍然存在。

一个例子是Foo是Car and Bar的驱动程序。汽车可能有也可能没有司机,但仍然是汽车,因此汽车中的指针会更有意义。此外,这允许通过简单地改变指向它的指针来改变汽车中的驾驶员。

答案 1 :(得分:0)

这应该是安全的。如你所示,你当然不应该删除栏,因为它将被Foo的析构函数删除。如果父母被设置在栏上以便不会发生双重删除,则应该小心。

答案 2 :(得分:0)

保存且100%有效。但是,第二段代码只有在Bar具有不带参数的构造函数时才有效。

但是,如果Bar的构造函数需要参数,您仍需要将其创建为Foo构造函数的初始化列表的一部分。

class Foo: public QObject {
    Q_OBJECT
public:
    Foo(QObject *parent = nullptr) 
    : QObject(parent)
    , bar(arg1, arg2)
    { }
private:
    Bar bar;
};

答案 3 :(得分:0)

更好的问题是:为什么通过bar作为指针的额外间接来过早地使代码失望?第二种方式不仅安全(为什么不安全?),由于引用的局部性,堆碎片等原因,它是首选的。第二个代码片段中唯一缺少的是初始化酒吧的父母。如果您希望将Foo实例移动到另一个线程,则需要这样做。如果不这样做,你会过早地随意限制Foo的功能。

在C ++ 11中:

class Bar : public QObject { ... };

class Foo: public QObject {
    Q_OBJECT
public:
    Foo(QObject *parent = nullptr) : QObject(parent) {}
private:
    Bar bar { this };
};