为什么Qt使用d_func()来实例化指向私有数据的指针?

Nat*_*man 9 c++ qt pointers

考虑以下Qt类:

#include <QScopedPointer>

class MyClassPrivate;
class MyClass
{
    public:
        MyClass();
        ~MyClass();
    private:
        QScopedPointer<MyClassPrivate> d_ptr;
        Q_DECLARE_PRIVATE(MyClass)
}
Run Code Online (Sandbox Code Playgroud)

此类类似于实现私有实现的大多数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;
Run Code Online (Sandbox Code Playgroud)

这很令人困惑 - 为什么不d_ptr直接在成员函数中使用?换句话说,而不是这样做:

Q_D(MyClass);
d->member = 12345;
Run Code Online (Sandbox Code Playgroud)

为什么不这样做?

d_ptr->member = 12345;
Run Code Online (Sandbox Code Playgroud)

具有显式函数的原因是什么(基本上)只是返回d_ptr并导致堆栈上额外变量的开销?

Min*_*Lin 9

如果派生类和基类都具有Private结构,则会浪费更多内存,因此在Qt中,私有类也是继承的,派生类和基类共享一个d_ptr.这样做的问题是d_ptr现在是BasePrivate类型.

class Base
{
protected:
    BasePrivate * d_ptr;
}

class Derived
{
// There is not d_ptr declared
}
Run Code Online (Sandbox Code Playgroud)

所以你可以在派生类中看到,当它访问d_ptr时,类型是BasePrivate*.所以它需要将d_ptr强制转换为DerivedPrivate*.d_func函数是内联的,一旦编译,它将始终将d_ptr强制转换为正确的类型.

这篇文章比我在这里说的更好,我建议你阅读它.