c++ - 什么是更好的?如果 child 是类的成员,是否为 child 设置 QObject 父级?

标签 c++ qt

class A : public QObject {
  A() : b(this) {} // !


  class B : public QObject {
    B(QObject* parent)
  };
  B b;
}

如果子对象不是动态的,我应该设置父对象吗?这两种情况有什么区别?

什么更好,有什么区别?

class A : public QObject {
  A() : b(new B(this)) {} // !


  class B : public QObject {
    B(QObject* parent)
  };
  B* b;
}

class A : public QObject {
  A() : b(new B()) {} // !


  class B : public QObject {
    B()
  };
  smart_ptr<B> b;
}

最佳答案

QObject 出身和存储持续时间是正交问题,应单独解决。

您无法将持有其他 QObjectQObject 移动到另一个线程,除非所有拥有的对象都将所有者设置为父对象。因此,如果不设置父类,就会过早地限制父类的功能。

在现代 C++ 中,具有动态存储持续时间的子 QObject 应通过资源管理器保存。这样的管理器可以是智能指针,或者只是拥有对象。回想一下,QObject 隐式地也是一个 QObject 容器。因此,甚至不需要有一个指向子对象的显式成员指针 - 比如说,如果您只需要在构造所有者期间直接引用该对象。

一般来说,通过拥有具有动态存储持续时间的任何成员,您会过早地悲观,除非它们的构造函数非常昂贵并且您希望将构造推迟到稍后的时间点。

所以,如果您不使用 PIMPL idiom ,那么所有成员都应该在对象本身中具有自动存储期限:

// A.h
class A : public QObject {
  Q_OBJECT
  QSerialPort m_port { this };
  QThread m_thread { this };
  ....
};

否则,它们属于 PIMPL:

// A.h
class APrivate;
class A : public QObject { ... };

// A.cpp
#include "A.h"
class APrivate {
public:
  A * const q_ptr;
  QSerialPort m_port { q_ptr };
  QThread m_thread { q_ptr };  
  APrivate(A * q) : q_ptr(q) {}
};

还应该指出的是,使用指向前向声明的不完整类型的指针来“加速”编译或“减少依赖关系”是一种反模式。如果您愿意在头文件中公开实现细节,只需按值保留所有可以的成员 - 如上面的第一个示例所示。如果您担心过多的依赖性并希望隐藏您的实现,请使用 PIMPL。向前声明类的指针的“中间道路”迫使您进行额外的动态存储分配,因此是一种不灵活的怪物,对任何人都没有帮助。

// DO NOT WRITE CODE LIKE THIS!!
class QSerialPort;
class QThread;
class A : public QObject {
  Q_OBJECT
  QSerialPort * m_port;
  QThread * m_thread;
  ...
};
// DO NOT WRITE CODE LIKE THIS!!

关于c++ - 什么是更好的?如果 child 是类的成员,是否为 child 设置 QObject 父级?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33238236/

相关文章:

c++ - 如何添加对 Boost.Proto 表达式的父引用?

c++ - 逐行读取文件并存储不同的变量

qt - 对 QMainWindow 的大小调整使用react以调整小部件的大小

c++ - 处理和触发从 QML 到 C++ 的事件,反之亦然

c++ - 使用opencv编译头文件。自己的类定义

c++ - 实际结构尺寸

c++ - 如何通过另一个项目在QT C++中运行一个项目?

c++ - 使用 Qt creator 编写屏幕保护程序 - 在屏幕保护程序设置中显示预览

c++ - 从内存中的 SVG 内容创建 QIcon

c++ - CMake链接另一个项目中的单个类