PrevUpHomeNext

Behind the Interface

The second fundamental property of the Pimpl idiom is the implementation hiding. Not only notionally declared private, not merely separated into another class or a header file, but truly internal and hidden (from the user). Behind the public interface it is all for developers to implement, to modify, to optimize, to improve as they need.

Still, the deployment pattern is fairly straightforward and reasonably self-documented. Something like the following will be tucked away in an implementation file:

template<> struct boost::impl_ptr<Book>::implementation
{
   implementation(string const& the_title, string const& the_author)
   :
       title(the_title), author(the_author)
   {}
   ...
   bool check_isbn_10_digit();
   ...
   string  title;
   string author;
   int     price =0;
};

Book::Book(string const& title, string const& author)
:
    impl_ptr_type(in_place, title, author) {}

string const& Book::author () const { return (*this)->author; }
void          Book:: price (int new_price) { (*this)->price = new_price; }

bool
Book::some_function() const
{  ...
   bool is_valid = (*this)->check_isbn_10_digit();
   ...
}

Again, the public Book class describes and implements the public interface (behavior) and the internal impl_ptr<Book>::implementation encapsulates private implementation (data and behavior).

As mentioned earlier, if comparison functionality is required, a class with value semantics will have to implement something like the following:

bool
Book::operator==(Book const& other) const
{
   return (*this)->title == other->title && (*this)->author == other->author;
}

Here the impl_ptr<Book>::implementation is again a struct rather than a class. As long as impl_impl<Book>::implementation is local to one file, i.e. private (although physically rather than notionally), there is generally little value in making it a class.

:-) Another reconciliatory and unifying property might be that no need to fight over a particular naming convention to draw attention to member variables (like the leading or trailing underscores, the 'm_' prefix or the myriad others). Member variables can be named naturally, accessed and identified as impl.title or (*this)->title or something of that sort.


PrevUpHomeNext