Why are private members/methods defined in the interface?
I've always been confused开发者_如何学Python by the fact that most OOP languages (or rather, C++) make you define private methods/members in the interface (by interface I mean the class declaration - seems like I was confused). Isn't this showing the implementation details of the class and going against the idea of encapsulation?
Is there a good reason for this that I've been missing?
For C++ it's an implementation issue.
The C++ compiler must be able to generate code that uses a class by only seeing the class declaration and not the implementation. One very important thing that is needed by the compiler is the size of an instance of the class because among other things C++ handles sub-objects in objects by embedding and not by storing a reference to a separate object. To be able to build an object (e.g. struct X { Y y; Z z; }
) the size of all sub-objects (e.g. Y
and Z
) must be known in advance.
A workaround for this problem is to use the "pimpl" pattern (also named the "compiler firewall" pattern) that allows you to keep all internal details hidden from the users of a class. This unfortunately carries some runtime extra cost with it but most the time it's a negligible one. With this approach the public object will always have the size of a pointer and all data in the instance will be accessed using an extra indirection... the advantage is that you can add private data members and users of the class don't need to be recompiled (and if your class is for example in a DLL this allows to maintain even binary compatibility).
Being able to declare just private methods (no data) in the implementation part would have been possible without any added complexity on the compiler, but C++ designer thought it was better to keep one single declaration for a class instead.
Actually even just adding a private method may affect the size of the a class instance in many implementations (e.g. if the private method is the only virtual one in the class).
C++ is the only language that I know which does this; notably, there are several functional languages which strictly separate the declaration of public and private interfaces. And notice that C++ makes a difference between declaring and defining: you only need to declare private functions in the interface, not define them.
For member variables as well as virtual functions, there is a simple technical reason: they influence the physical layout of the class. Since this layout needs to be identical across translation units, all units need to know the layout – and hence the physical makeup of the class.
I suspect that you also need to declare non-virtual functions publicly in C++ just to keep it consistent: otherwise, you’d have to declare different functions in different places, depending on whether or not they are public and/or virtual.
You can circumvent this restriction by using the handle-body idiom (also known by its cosmetically less appealing name “PIMPL”) but this adds its own complexity to the solution.
In the particular case of C++, one reason is that the declaration of all virtual functions -be them public or private-, is needed in order to generate the virtual pointer table. Probably the same reason applies to other languages as well.
This does not go against the idea of encapsulation, private methods/members are not part of the PUBLIC interface so the data remains encapsulated. Besides, public/private modifiers enforce only visibility.
There are two senses, in which the word interface is used in C++: an OOP interface and a type declaration.
An OOP interface is used for encapsulation and polymorphism. In C++, it is usually implemented with pure abstract classes. The PIMPL idiom is also used for encapsulation. In either case, the consumer is shown only the type's public members and accesses the private implementation through an indirection layer. Java and C# support explicit interfaces and both restrict their members to public access.
Type declarations are required in C++ due to its linking model. A type's declaration is not its interface in the OOP sense, but because a type's declaration has to be included before use, decoupling the implementation becomes more desirable. In order to achieve this, we use OOP interfaces, as described above. There would be no need to hide private implementation details from a type's declaration, if only C++ supported modules. Module support was proposed for C++11, but due to time constraints set to be included in a future TR.
There are many tricks to solve that problem in C++.
You can use factory pattern to hide the private members and methods to users.
What you need is to create a abstract class
as your API or interface, than implement your class in subclass and declare all your private members there, in this way your users won't see your private members and implementations.
How do you get such a conclusion? I found no OOP languages that makes me do so. For C++, the reason people define methods in interface is for inlining purpose. For members, well that's because you can't define it anywhere else, and it applies to all visibilities, not just private.
精彩评论