我们通常编写拥有其他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()
”吗?
答案 0 :(得分:2)
是的,这是安全的,只要您不尝试删除栏,因为它会在删除Foo后自动释放。
可以说,决定走哪条路取决于实际Foo
和Bar
是什么。
当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 };
};