Ivan Čukić

D-Ptr, the modern way

The KDE libraries (and some other parts as well) require that the code uses the so called d-pointer or pimpl (private implementation) idiom (see [1] and [2]). It makes it easier to keep the ABI unchanged, and it speeds up the compilation with insignificant runtime costs.

It usually goes like this – declare a Private class and a const pointer to it named d and (de)initialize it properly. Instead of having private class members, put them in that class. [2]

-- .h -------------------

class MyClass {
    :::
private:
    class Private;
    Private * const d;
};

-- .cpp -----------------

class MyClass::Private { ::: };

MyClass::MyClass()
    : d(new Private())
{
    d->name = "I'm a private class member to replace m_name :)";
}

MyClass::~MyClass()
{
    delete d;
}

-------------------------

This works. But having explicit new and delete operators is generally frowned upon in the modern C++ world. It is quite easy to forget to add the delete d to the destructor. And it is nothing more than unnecessary boilerplate. The example at [1] improves this situation by using the QScopedPointer which automatically does the deletion for you.

With the new C++11 features (these are available since gcc 4.4), this can be made even cleaner.

.h ----------------------

class MyClass {
    :::
private:
    class Private;
    d_ptr<Private> d;
};
.cpp ----------------------------

class MyClass::Private { ::: };

MyClass::MyClass()
{
}

MyClass::~MyClass()
{
}

No special handling of d, no new and no delete. Even if the Private class had a constructor with arguments, the implementation would be pretty:

.h ----------------------

class MyClass {
    :::
private:
    class Private;
    d_ptr<Private> d;
};
.cpp ----------------------------

class MyClass::Private {
    
    Private(t1 arg1, t2 arg2)
    { ::: }
};

MyClass::MyClass()
    : d(arg1, arg2)
{
}

MyClass::~MyClass()
{
}

For the implementation of d_ptr class, you can see the d_ptr.h and d_ptr_implementation.h from kactivities repo [3].

Now, the code is perfectly safe. If you make a mistake, it will be detected by the compiler, and will not propagate to runtime.

[1] Library_Code_Policy:D-Pointers
[2] Binary Compatibility Issues With C++
[3] kde:kactivities

Loading comments...