QT pimpl 从 QObject 继承

use*_*867 5 inheritance qt private

在查看 Qt 代码时,我对 pimpl 实现有一个基本问题。以 QWidget 实现为例。

QWidget        ---inherits---> QObject
   |                              |
 contains                      contains
   |                              |
  \ /                            \ /
QWidgetPrivate ---inherits---> QObjectPrivate
Run Code Online (Sandbox Code Playgroud)

现在 QWidget 有两个 QObjectPrivate 实例(通过继承和通过包含)。为什么要这样实施呢?拥有同一个对象的两个实例不是一种开销吗?

Gra*_*erg 4

QObjectPrivate实例化 时不存在两个实例QWidget。如果仔细查看 的头文件QObject,您会注意到一个受保护的构造函数:

protected:
    QObject(QObjectPrivate &dd, QObject *parent = 0);
Run Code Online (Sandbox Code Playgroud)

它将 QObjectPrivate 的实例设置为通过 protected 构造函数传入的实例:

QObject::QObject(QObjectPrivate &dd, QObject *parent)
    : d_ptr(&dd)
Run Code Online (Sandbox Code Playgroud)

这是由所有不同QWidget构造函数调用的构造函数。QWidget 构造函数传入一个实例QWidgetPrivate,正如您所指出的,该实例是QObjectPrivate. 因此,QWidget 中只存在一个 QObjectPrivate 实例。

这是QWidget说明这一点的默认构造函数:

QWidget::QWidget(QWidget *parent, Qt::WindowFlags f)
    : QObject(*new QWidgetPrivate, 0), QPaintDevice()
{
    QT_TRY {
        d_func()->init(parent, f);
    } QT_CATCH(...) {
        QWidgetExceptionCleaner::cleanup(this, d_func());
        QT_RETHROW;
    }
}
Run Code Online (Sandbox Code Playgroud)