Compiling firewall-parsing Pimpl usage in C ++

Source: Internet
Author: User

Compiling firewall-parsing Pimpl usage in C ++

Pimpl(Pointer to implementation, pointing to the implemented pointer) is a common method used to decouple "class interfaces and implementations. This technique avoids exposing private details in header files (see figure 1). Therefore, it is an important mechanism to promote full separation between API interfaces and implementations. However, Pimpl is not a strict design model (it is a flexible solution subject to the specific limitations of C ++). This practice can be seen as a special case of the bridge design model.

Figure 1: Pimpl usage. The public class here has a private pointer pointing to a hidden implementation class.

Using Pimpl in a class has the following advantages:

  • Reduced Coupling
  • Information Hiding
  • Reduces compilation dependencies and increases Compilation speed
  • Separation of interfaces and Implementations

To implement Pimpl, Let's first look at the design method of a common class.
Suppose we want to design a book categoryBookThe Book contains directory attributes and provides an external interface for Printing Book information. The Book design is as follows:

class Book{public:  void print();private:  std::string  m_Contents;};

Book users only need to knowPrint ()Interface, you can use the Book class, and everything looks wonderful.
However, one day, I found that the Book needs to add a title attribute. The changes to the Book class are as follows:

class Book{public:  void print();private:  std::string  m_Contents;  std::string  m_Title;};

Although the print () interface can still directly output the Book information, the Book class users have to re-compile all the code containing the Book Class header file.
To hide the implementation details of the Book class and truly separate interfaces from implementations, you can use the Pimpl method.
We still provide the same interface for the Book class, but the Book class does not contain the original data members, and all its operations are implemented by the BookImpl class.

/* Public. h */# ifndef PUBLIC_H_INCLUDED # define PUBLIC_H_INCLUDEDclass Book {public: Book ();~ Book (); void print (); private: class BookImpl; // Book Implementation class pre-declaration BookImpl * pimpl;}; # endif

In the external header filePublic. hContains only the external interfaces of the Book class, and encapsulates the real implementation detailsBookImplClass. To avoid exposing the BookImpl class externally, declare it as the embedded class of the Book class and declare it as private.

The header file of the BookImpl class is as follows.

/* private.h */#ifndef PRIVATE_H_INCLUDED#define PRIVATE_H_INCLUDED#include "public.h"#include <iostream>class Book::BookImpl{public:  void print();private:  std::string  m_Contents;  std::string  m_Title;};#endif

Private. hIt does not need to be provided to Book users. Therefore, if you need to re-design the attributes of the Book class in the future, the outside world knows nothing about this, so as to maintain the immutability of interfaces and reduce the compilation dependency between files.

/* Book. cpp */# include "private. h "// we need to call the BookImpl class member function, // so we need to include the BookImpl definition header file # include" public. h "// we are implementing the Book class, so we need to include the Book Class header file Book: Book () {pimpl = new BookImpl ();} Book ::~ Book () {delete pimpl;} void Book: print () {pimpl-> print ();}/* BookImpl class implementation function */void Book: BookImpl :: print () {std: cout <"print from BookImpl" <std: endl ;}

The method for using the Book class interface is as follows:

/* main.cpp */#include "public.h"int main(){    Book book;    book.print();    return 0;}

Classes that use Pimpl like Book classes are often calledHandle class, BookImpl class as the implementation class, calledImplementation class.

For simple implementation, the Book class skips the copy constructor and the copy assignment function. In practical applications, there are generally two options to solve the semantic problem of Book copying and assignment.

(1) prohibit Replication
If you do not want to create a copy of the object, you can declare the object as non-replicable. You can declare the copy constructor and copy assignment function as private, so that compilation errors will occur during the copy or assignment.
The following Code declares a private copy constructor and a copy value assignment function to prevent objects from being copied and does not need to modify related. cpp files.

/* Public. h */# ifndef PUBLIC_H_INCLUDED # define PUBLIC_H_INCLUDEDclass Book {public: Book ();~ Book (); void print (); private: // prohibit copying class Book (const Book &); const Book & operator = (const Book &); class BookImpl; // BookImpl * pimpl;}; # endif

(2) display definition replication Semantics
If you want to copy objects using Pimpl, you should declare and define your own copy constructor and copy the value assignment function. They can perform deep replication of objects, that is, creating copies of objects instead of copying pointers.

The main drawback of Pimpl's usage is that you must allocate and release implementation objects for each object you create, which adds a pointer to the object. Each call to the handle class member function must pass implementation class, this adds an indirect layer. In practice, you need to weigh these overhead.
In addition, if you use Pimpl objects, the compiler will no longer be able to capture modifications to member variables in the const method. This is because the member variables exist in independent objects. The Compiler only checks whether the pimpl pointer in the const method changes, and does not check any member pointed by pimpl.

You can use 2 to describe the role of the Pimpl method in the above Book class design:


Figure 2: Using Pimpl as the firewall for compiling

Pimpl removes the coupling between interfaces and implementations, thus reducing the compilation dependency between files. Therefore, Pimpl is often called "firewall during compilation".

The sample code in this article can be downloaded through the following link: Download link

References

Copyright statement: This article is the original author article, reprint please indicate the source: http://blog.csdn.net/lihao21

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.