[Cat * G Translation Project GotW # 22-30: Draft]
Gotw # 24 compilation firewalls: Herb Sutter Translation: Cat * G [Declaration]: This article takes the Guru of The Week section on www.gotw.ca website, and its copyright is owned by the original. Translator Cat * G translates this article without the consent of the protocol. This translation is only for self-study and reference, please read this article, do not reprint, spread this translation; people download this translation content, please delete its backup immediately after reading. Translator Cat * G is not responsible for people who violate the above two principles. This declaration. Revision 1.0
GURU Of The Week Terms 24: Compiling Level Firewall
Difficulty: 6/10
(Use the PIMPL usual method to greatly reduce the interdependence between the code, and reduce the establishment time of the program. But what should I put in the PIMPL object? How can I use it safely?)
[Problem] [Question]
In C , if any part of the class definition is changed (even private member), then all of this class must recompile. In order to reduce this dependency, a common technology used is to hide some implementation details using an opaque pointer:
Class X {public: / * ... public member ... * / protected: / * ... protection member? ... * / private: / * ... private member? ... * / class XIMPL * PIMPL_; // Points to a forward-declared class // opaque pointer};
[Quothes] [Question]
1. Those portions should put them in XIMPL? There are four common principles, they are:
- Put all private data (but not functions) into XIMPL; - put all private members (translation: ie, including functions) into XIMPL; - put all private members and protection members into XIMPL; - Make XIMPLs completely X The X is written as a common interface consisting entirely of a simple front function (a variant of the handle / body).
What excellent shortcomings do they have? How do you choose the right?
2. XIMPL needs a "Back Pointer" "pointing to the X object?
[Solution] [answer]
First look at two definitions: Visible Class: Class of customer generation and manipulation (here is X). PIMPL: The visible class is hidden in a transparent pointer (also known as PIMPL_) (herein XIMPL).
In C , if any part of the class definition is changed (even private member), then all of this class must recompile. In order to reduce this dependency, a common technique for use is to hide some of the opaque pointer (Opaque Pointer) to implement detail: this is a variant of the "Handle / Body IDiom). As described in Coplien [Note 1], this method is mainly used to make a reference count in the case of shared code.
As indicated by Lakos [Note 2], "handle / body" is used to use (manifesting as "PIMPL usual method" in the "PIMPL ingredients", such a legal self-pronounced "PIMPL_ "Pointer [Note 3]) is also very useful for breaking the dependence of the compilation period. The solutions of this Territor are discussed in this use, and some of which discusses the general discussion.
The main cost of using this usual method is performance:
1. Each constructor must allocate memory. Custom Allocator may alleviate additional consumption of memory, but this is not involved more work.
2. Each hidden member requires an additional indirect layer to access it. (If the hidden member of the visited itself uses a "Back Pointer" to call the function in the visible class, then there will be double indirectness.)
1. Those portions should put them in XIMPL? There are four common principles, they are: - put all private data (but not functions) into XIMPL;
This is a good start, because now we have to make a pre-declaration for any class only as a data member (not using the #include statement to include the true statement of the class - this will enable customer code to Dependence). Of course, we can usually do better.
- Put all private members (translation: ie, including functions);
This (almost) is my usual usage. In any case, in C , "customer code should not care about these parts" means "private", and private things are best hidden (in some "free and wide" laws. Except for the situation in the Nordic countries).
There are two warnings to this, the first one is the reason I am in the previous paragraph: Almost:
1. Even if the virtual function is private, you cannot hide the virtual member function in the PIMPL class. If you want the virtual function overwritten the same name virtual function in the base class, then the virtual function must appear in a real derived class. If the virtual function is not inherited, then in order to override the layer-level derived class, it must still appear in the visible class.
2. If a function in PIMPL uses other functions, it may require a "backpoint" pointing to visible objects - this further adds a layer of indirectivity. This reverse pointer is usually referred to as Self_.
- Put all private members and protect members in XIMPL;
This further practice is actually wrong. Protection Members should never be placed in PIMPL, because this is equal to it is not used. In any case, Protected Members is exist in order to make the derived class to see and use, so if the derived class can't see or use them, they are basically unused. - Make XIMPL to the original X, write X as a common interface consisting entirely of a simple pre-front function (a variant of a handle / body).
This is only useful in a few limited cases, and the advantage is to avoid the use of reverse pointers because all services are available in the PIMPL class. Its main disadvantage is that this will generally make visible classes for inheritance, whether it is a base class or derived class.
2. XIMPL needs a "Back Pointer" "pointing to the X object?
Unfortunately, answering usually "Yes". In any case, we will split every object into two parts - just because we have to hide some of them.
When the function in the visible class is called, some of the functions and data in the hidden part (the translation:, the PIMPL section) are often needed to complete the request to be called. This is quite good, it is also very reasonable. However, it may not be obvious that the function in the PIMPL often must call the function in the visible class - usually because the function that needs to be called is a public member or a virtual function.
[Note 1]: James O. Coplien. Advanced C Programming Styles and IDioms (Addison-Wesley, 1992).
[Note 2]: J. Lakos. Large-Scale C Software Design (Addison-Wesley, 1996).
[Note 3]: I used to write it to IMPL_. With its equivalent, PIMPL_writing is actually proposed by my friend and colleague Jeff Sumner; Jeff Sumner is the same as the Hungarian "P" prefix for pointer variables as me (translation: ie Hungarian representation) for naming variables; In this representation, the pointer variable name begins with "P", meaning "Pointer") is quite increasingly sensitive, and it has a unique sensitivity to the horrible dual-definition (translation: PIMPL pronunciation and word "PIMPLE (meaning acne , Pimple, pustule, sputum, acne) "the same).
(Finish)