Hiding private members of a C ++ library

I wrote a library (no matter what it does), which obviously has its own header file. Now I want to hide the private elements of this header file, so if I give my library to someone, it should see only public members (preferably, not a class definition, nothing more than function definitions). One way is to create a C-style header that will contain some kind of β€œinit” method that will be used to instantiate the actual library class, and the user will have to pass a pointer to this object for each function to do the job.

Is this a good practice?

Are there any other common ways to do something like this?

Thanks in advance.

+7
c ++ shared-libraries static-libraries
source share
5 answers

In addition to the Factory template (which, in my opinion, can become cumbersome), you can also hide your personal members behind the PIMPL (pointer to IMPLementation):

// Interface.hpp class Implementation; class Interface { public: Interface() : pimpl(new Implementation()) {} void publicMethod(); private: std::unique_ptr<Implementation> pimpl; }; // Interface.cpp class Implementation { public: void PrivateMember(); }; void Interface::publicMethod() { pimpl->PrivateMember(); } 

This has the advantage of hiding the implementation due to a unidirectional pointer, not unlike the typical Factory inheritance pattern.

It can also be stable ABI. Changes in your implementation will not affect the binding, since no changes will ever be visible to the rest of the program. This is a good template to use, for example, when implementing shared objects.

This is also a common C ++ idiom, which is why other C ++ programmers recognize it without question.

In the case of a class that follows the Singleton pattern, you can skip PIMPL at all and just write the entire implementation in an anonymous namespace in your .cpp file, where you can add as many public and private functions as you wish without even hinting at it in its interface.

+11
source share

You can create a visible interface. Create an abstract class with the functions you want to open, and then continue with the implementation.

For example, the interface:

 class Interface { public: virtual void publicMethod() = 0; ... }; 

And implementation:

 class Implementation : Interface { public: virtual void publicMethod(); private: int hiddenMethod(); }; 

Then you export only the characters for the interface. Now, so that the library user can get the instances of the interface, which are actually implementations, you need to provide a factory:

 class Factory { public: //can create and return an Implementation pointer, but caller will get an Interface pointer std::shared_ptr<Interface> getImplementationInstance(); } 
+6
source share

Based on Eric Finn's Answer , you can simply declare an interface class to store all of your public methods that are considered your API, and hide all implementations and private members / methods in the implementation class that inherits from the interface class, here is an example:

Your header file: my_api.h

 // your API in header file // my_api.h class interface { public: static interface* CreateInstance(); virtual void draw() = 0; virtual void set(int) = 0; }; 

your implementation (shared library): my_api.cpp (users will not see this when you make it a shared library) This way you can hide all your implementations and private methods / members here.

 #include "my_api.h" // implementation -> in .cc file class implementation : public interface { int private_int_; void ReportValue_(); public: implementation(); void draw(); void set(int new_int); }; implementation::implementation() { // your actual constructor goes here } void implementation::draw() { cout << "Implementation class draws something" << endl; ReportValue_(); } void implementation::ReportValue_() { cout << "Private value is: " << private_int_ << endl; } void implementation::set(int new_int) { private_int_ = new_int; } interface* interface::CreateInstance() { return new implementation; } 

How the user uses your API:

 #include <iostream> #include "my_api.h" int main(int argc, const char * argv[]) { using namespace std; interface* a; interface* b; a = interface::CreateInstance(); a->set(1); b = interface::CreateInstance(); b->set(2); b->draw(); a->draw(); return 0; } 

Output:

 Implementation class draws Private int is: 2 Implementation class draws Private int is: 1 

In this template, your api is just an abstract class that works like a factory, you can also implement a virtual method in different classes and specify which instance you want to call.

+2
source share

I think you need to create a dynamic link library (dll).

Please quickly review this link:

+1
source share

You might want to take a look at the envelope / letter idiom, bridge design template, or proxy template. Basically, you would create an external (public) class that simply redirects your calls to public methods to an internal (private) class. The InnerClass.h header should be visible / known to your OuterClass.cpp and InnerClass.cpp source files.

Each of these patterns provides an implementation branch mechanism from the interface, so the caller is not associated with the implementation. Sometimes you need to reduce the compiler’s dependence on large C ++ projects. Another common reason you want to do this is simply when you want to hide implementation details so that the calling user sees only one opaque pointer.

 ======= OuterClass.h ===== class InnerClass; // forward declaration is all that needed class OuterClass { private: InnerClass *pInner; public: InnerClass(); bool doSomething(); }; ======= OuterClass.cpp ====== #include "OuterClass.h" #include "InnerClass.h" OuterClass::OuterClass() : pInner(new InnerClass()) { } bool OuterClass::doSomething() { return pInner->doSomething(); } 
0
source share

All Articles