Domanda

Nella sezione "Good incapsulamento" in codice completo, si consiglia di nascondere i dettagli implementativi private. Un esempio è dato in C ++. L'idea è sostanzialmente quella di separare completamente l'interfaccia con l'applicazione, anche nel livello di classe.

class Employee {
public:
    ...
    Employee( ... );
    ...

    FullName GetName() const;
    String GetAddress() const;

private:
    EmployeeImplementation *m_implementation;
};

Questa è davvero un buon uso del tempo? Non solo questo sembra inefficiente (che tipo di sanzioni prestazioni sarebbe questo danno?), Ma tutto il motto di codice completo ( "gestione della complessità") sembra essere stato invertite, fa questo non Aggiungi complessità?

È stato utile?

Soluzione

Another advantage of the PIMPL idiom may be in maintaining the ABI. See The Pimpl Idiom in practice.

The size of the class remains constant. This means that you may change the internal implementation, while keeping the interface intact.

If the implementation is distributed in compiled form (lib, dll, so, etc.), then, under some conditions, you may be able to just replace the library without having to recompile the code that uses the class. Thus, you decouple the code as a completely stand-alone module, so long as the public interface doesn't change.

As others have stated, it also reduces compilation time, which can be reason enough in some cases.

Altri suggerimenti

Well, it does increase encapsulation since your header file now contains only public members and a single pointer to a private implementation.

It also (slightly?) lowers performance due to the extra level of indirection.

The "reduces compilation time" is the key issue here.

If you (your company) are the only users of the class then I don't think you have any reason to use this idiom. You get lower performance and you should have daily (or periodic) rebuilds of your source code anyway (which should be aware of dependencies between the classes).

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

If you are distributing the library then the story is completely different. Changes in headers mean any clients you have will need to rebuild their applications to use your new version, even if what you did was change the private parts of the class. Using the pimpl idiom here would mean the change is invisible to the users of your dynamic library.

An extra level of indirection through pointer can cause extra 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 having with all fields in the class, instead of just one pointer. Now, whenever you change employee details (e.g. add or remove field), EVERY file including employee.h has to be recompiled. If all you have is a single pointer to an implementation class defined in employee.cpp, then ONLY employee.cpp has to be recompiled when you change EmployeeImplementation.

Now, is the reduced compilation time worth the extra cost? Only you can decide that.

I think that the main advantage (or at least on of them) of the pimpl idiom is not saving compilation time, but allowing loose-coupling, i.e. breaking dependencies, between components.

Suppose you provide an infrastructure library that many other components use. Then, as @zvrba indicated, every time you change your private implementation details all your clients must recompile. It could be not a big deal, but in large and complex projects an integration between components may be a complex task. With pimpl, if your library is dynamic (dll, .so) then no action is required by your clients.

This idiom is used for abstracting over poor headers, and not much else. Only use it if the types required to define the class involve including headers which leak macros, take a long time to compile, etc. Apart from that, it's generally not considered the correct thing to do. Since your implementation requires dynamic allocation and reference semantics anyway, you may as well just make it an interface and offer a CreateForMyPlatform() method that has a definition in a cpp file. At least you can use smart pointers for that scenario.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top