C ++ encapsulation tips from Code Complete?

In the "Good Encapsulation" section of Code Complete, it is recommended that you hide the details of the private implementation. An example is given in C ++. The idea is to completely separate the interface from the implementation, even at the class level.

class Employee { public: ... Employee( ... ); ... FullName GetName() const; String GetAddress() const; private: EmployeeImplementation *m_implementation; }; 

Is this a really good time? Not only does this seem ineffective (what performance penalties can this give?), But the entire Code Complete motto ("complexity management") has apparently been canceled - doesn't that add complexity?

+6
source share
5 answers

Another advantage of the PIMPL idiom can be ABI support. See the Pimpl idiom in practice .

Class size remains constant. This means that you can change the internal implementation while maintaining the integrity of the interface.

If the implementation is distributed in compiled form (lib, dll, etc.), then under certain conditions you can simply replace the library without recompiling the code that the class uses. Thus, you disable the code as a fully autonomous module if the public interface does not change.

As others have argued, this also reduces compilation time, which may be the cause in some cases.

+3
source

Well, this increases encapsulation, since your header file now contains only public elements and a single pointer to a private implementation.

It also (slightly?) Reduces performance due to an additional level of indirection.

"Reducing compilation time" is a key issue here.

If you (your company) are the only users of the class, then I do not think that you have a reason to use this idiom. You get lower performance, and in any case, you should have daily (or periodic) modifications to the source code (which should be aware of dependencies between classes).

This means that compilation time should be pretty much irrelevant if you are the only consumer of the class.

If you distribute the library, the story is completely different. Changes to the headers mean that any customers you have will need to rebuild their applications to use their new version, even if what you did change the personal parts of the class. Using the pimpl idiom here would mean that the change is invisible to users of your dynamic library.

+2
source

An additional level of indirection through the pointer can cause additional cache misses and slow down your program. AFAIK, this idiom (PIMPL) is most often suggested to reduce compilation time. Say you have an employee.h header that has all the fields in the class, and not just one pointer. Now, whenever you change data about employees (for example, add or delete a field), EVERY file that includes employee.h must be recompiled. If all you have is a single pointer to the implementation class defined in employee.cpp , then ONLY employee.cpp needs to be recompiled when EmployeeImplementation changes.

Now, is reduced compilation time worth the extra cost? Only you can solve it.

+1
source

I think that the main advantage (or at least of them) of the idiom pimpl does not save compilation time, but it allows you to untie the links, i.e. depending on different components.

Suppose you provide an infrastructure library that many other components use. Then, as @zvrba pointed out, every time you change the details of your private implementation, all your clients must recompile. This may not be a big problem, but in large and complex projects, integration between components can be a daunting task. With pimpl, if your library is dynamic (dll, .so), your clients do not require any action.

+1
source

This idiom is used to abstract out the bad headings, and nothing more. Use it only if the types needed to define the class include headers that invoke macros, require a lot of time to compile, etc. In addition, this is usually not considered correct. Since your implementation requires dynamic allocation and reference semantics anyway, you can simply make it an interface and suggest the CreateForMyPlatform() method, which has a definition in the cpp file. At least you can use smart pointers for this scenario.

+1
source

Source: https://habr.com/ru/post/890320/


All Articles