2013-04-10 72 views
9

考慮下面的Qt類:爲什麼Qt使用d_func()來實例化指向私有數據的指針?

#include <QScopedPointer> 

class MyClassPrivate; 
class MyClass 
{ 
    public: 
     MyClass(); 
     ~MyClass(); 
    private: 
     QScopedPointer<MyClassPrivate> d_ptr; 
     Q_DECLARE_PRIVATE(MyClass) 
} 

該類類似於實現私有實現大多數Qt類的結構。宏Q_DECLARE_PRIVATE將導致以下膨脹(如QT5的):

inline MyClassPrivate* d_func() 
    { return reinterpret_cast<MyClassPrivate *>(qGetPtrHelper(d_ptr)); } 
inline const MyClassPrivate* d_func() const 
    { return reinterpret_cast<const MyClassPrivate *>(qGetPtrHelper(d_ptr)); } 
friend class MyClassPrivate; 

這是混亂 - 爲什麼不d_ptr在成員函數直接使用?換句話說,而不是這樣做:

Q_D(MyClass); 
d->member = 12345; 

爲什麼不這樣做呢?

d_ptr->member = 12345; 

什麼是對具有明確的功能(基本上)僅返回d_ptr,並會導致堆棧上的額外變量的開銷的原因嗎?

回答

7

如果派生類和基類都有一個Private結構,它會浪費更多的內存,因此在Qt中,私有類也被繼承,並且派生類和基類共享一個d_ptr。這樣做的問題是,d_ptr現在是BasePrivate類型。

class Base 
{ 
protected: 
    BasePrivate * d_ptr; 
} 

class Derived 
{ 
// There is not d_ptr declared 
} 

所以你可以看到,在派生類中,當它進入應將d_ptr,類型爲BasePrivate *。所以它需要將d_ptr轉換爲DerivedPrivate *。 d_func函數是內聯的,一旦編譯完成,它總是會將d_ptr轉換爲正確的類型。

This post說明比我在這裏說的更好,我建議你閱讀它。

+0

如果我的類沒有一個是相互繼承的,那麼使用'Q_DECLARE_PRIVATE'宏有什麼好處呢?繼承是內聯方法的唯一原因嗎? – 2013-04-10 04:44:38

+1

@NathanOsman我認爲應該沒有理由使用宏,如果你使用兩個不相互繼承的類。他們每個人都可以有一個單獨的實施。但事實是,在Qt中,幾乎所有的類都是從QObject類繼承而來的,並且有時繼承會非常深刻,如果沒有這樣的機制,它會給內存帶來很大的開銷。 – 2013-04-10 04:54:25

相關問題