0

I want to make a class-library using pimpl idiom, so that I can hide my implementation details for the user of the library.

Is it possible, to make a class, where some methods are public and callable from users perspective, while having methods that are only callable from the internals.

Right now I only see a solution with the friend keyword and declaring the internal methods private.

For example: MyPartiallyVisibleClass: Class containing a mixture of methods accessible to the user, and methods only accessible to the internals of library. InternalClass: Class internally in the library. The user will never know this excist.

// MyPartiallyVisibleClass.h: Will be included by the user.
class MyPartiallyVisibleClass
{
private:
    class Impl;          // Forward declare the implementation
    Impl* pimpl;

    InternalMethod();    // Can only be called from within the library-internals.

public:
    UserMethod();       // Will be visible and callable from users perspective.
}

// MyPartiallyVisibleClass.cpp
class MyPartiallyVisibleClass::Impl
{
private:
    InternalMethod();

public:
    UserMethod();

    friend class InternalClass;
}

// Internal class that will not be included into users application.
class InternalClass
{
public:
    InternalMethod()
    {
        MyPartiallyVisibleClass pvc;
        pvc.InternalMethod();
    }
}

Is there a better way of doing this?

abaldur
  • 29
  • 1
  • 3
  • Why do you need that? The easiest is to put only public methods in the user class, and leave all gory details to the implementation(s). – juanchopanza Aug 18 '13 at 07:14
  • Duplicate candidate: http://stackoverflow.com/questions/843389/the-pimpl-idiom-in-practice – lpapp Aug 18 '13 at 07:20
  • NOT A DUPLICATE: this question is more specific. unless to consider every question talking about pimpl a duplicate... – Emilio Garavaglia Aug 18 '13 at 07:44
  • Everything in here is covered by that post in my opinion. :) These topics are overdiscussed again, again, and again. I do not see anything specific in here than just the generic principles. – lpapp Aug 18 '13 at 07:49

1 Answers1

0

There are pros and cons.

By a source stand point, if you distribute only headers and binaries, everything in in cpp files will not be seen by the source user.

So, also MyPartiallyVisibleClass::Impl::Usermethod is not visible, but being public, callable everywhere in the cpp file it is declared.

Zero way, one way or two way friendship between external and internal class can be required if you don't want to repeat external methods internally. It can seem an encapsulation break, but it is not, since the "capsule" here, is the external class. Creating complex hierarchy of intenal privacy (public external, private external, public internal private internal public even more internal ... etc.) can become clueless if everything goes under your same responsibility. Unless the internal part is so large to be assigned to different developers, so that another level of interface & implementation is needed.

By a binary user standpoint, however, every function that is not inlined exist, and -having external linkage- its name is available into the library, and hence it is "callable" by writing another header that makes it publicly available to other sources. I will just be an undocumented feature.

The concept of public/private etc. is for code safety (avoid function you don't want to promise to maintain with always the same "contract" to be available, thus making external code more stable, eliminating unwanted dependency) not for "security" (avoid who wants to call to find a way to call).

There is then also another drawback: templates cannot be hidden into sources, since they have to be expanded into the users's source code space (not the developer binary space). And the growing of generic programming, functional static polimorphism etc. makes the pimpl idiom less and less attractive.

There are today many programs made by a single cpp file that instantiate a single "manager object" whose entire functionality reside as is made of header only libraries. Believing or not, this way to program makes code even more portable between compilers, since it doesn't have to exist in a different binary form for every possible client compiler. And does not necessarily make build time longer: precompiled header can be generated once for code that don't change too often. Who cares is the user ca see the code? If he wants to use it and be supported is not his interest to change it improperly. If he wants to hack or stole, he will find anyway another way to do it.

Emilio Garavaglia
  • 18,858
  • 2
  • 41
  • 60
  • Actually, pimpl is still pretty common nowadays, so the "less and less attractive" might be understood by others. It *is* still very attractive. In fact, despite this post, I would personally suggest the pimpl idiom for use. What is probably worse is these 1-2 ways friends. – lpapp Aug 18 '13 at 07:53
  • @LaszloPapp: then the standard library is worst, at least for you. But don't worry, it's an old debate: see http://stackoverflow.com/questions/1093618/how-does-the-friend-keyword-class-function-break-encapsulation-in-c – Emilio Garavaglia Aug 18 '13 at 08:46
  • No, I have not said that it is ultimately bad. I said for this scenario, it is not the right call, IMO. :-) – lpapp Aug 18 '13 at 09:06