2011-06-28 59 views
4

在經歷Qt代碼時,我對pimpl的實現有了這個基本問題。 以QWidget實現爲例。來自QObject的QT pimpl繼承

QWidget  ---inherits---> QObject 
    |        | 
contains      contains 
    |        | 
    \/       \/
QWidgetPrivate ---inherits---> QObjectPrivate 

現在QWidget有兩個QObjectPrivate實例(通過繼承和通過包含)。 爲什麼以這種方式完成實現?擁有同一個對象的兩個實例不是一個開銷嗎?

回答

4

實例化QWidget時不存在兩個QObjectPrivate實例。如果你在爲QObject頭文件仔細觀察,你會發現一個受保護的構造:

protected: 
    QObject(QObjectPrivate &dd, QObject *parent = 0); 

其中QObjectPrivate實例設置對通過受保護的構造函數傳遞:

QObject::QObject(QObjectPrivate &dd, QObject *parent) 
    : d_ptr(&dd) 

這是構造函數由所有不同的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; 
    } 
}