chocobo_ff
chocobo_ff

Reputation: 560

Private/public header example?

Can someone please give me an example of how public and private headers work? I have done some reading on the net but I can't seem to find much useful information with sample codes. I was advised that I should use private headers to separate the public and private parts of my code for creating a static library. After some reading I have a general idea of how it works, but would really appreciate a good example to get me started. Specifically, what I don't quite understand is how to put the interface functions in my public header, and the private variables/functions in my private header? Thanks!

EDIT:

Maybe I'm not wording my question right, but what I meant is, for example, I have myMath.h and myMath.cpp, and myMath.h has:

class myMath{
public:
    void initialise(double _a, double _b);
    double add();
    double subtract();

private:
    double a;
    double b;
};

And myMath.cpp has the implementations of the functions. How can I make it so that myMath.h only has the three public functions, and the private variables are defined in another file (e.g. myMath_i.h), and these three files are in such a way that after I create a static library, only myMath.h is needed by users. This also means myMath.h cannot #include myMath_i.h. So something like:

myMath.h:

class myMath{
public:
    void initialise(double _a, double _b);
    double add();
    double subtract();
}

and myMath_i.h:

class myMath{
private:
    double a;
    double b;
}

Of course that's not possible because then I'll be redefining the class myMath...

Upvotes: 42

Views: 68562

Answers (5)

Daniel Schuler
Daniel Schuler

Reputation: 3150

I've actually found the two-header-one-source approach to be fragile. If you forget to update the 'public' header after changing the 'private' header, your code may compile, and then segfault somewhere else at run time. I've had this happen to me a few times, so I prefer to write code that won't compile unless everything is correct.

MyClass.cpp is implemented like this:

#define MYCLASS_IMPL
#include "MyClass.h"

// Implementation follows
...

MyClass.h is the interesting bit:

#ifdef MYCLASS_IMPL
#include everything needed for the private: section
#endif

#include everything needed for the public: section only

class MyClass
{
public:
    // Everything that's public

#ifdef MYCLASS_IMPL
private:

    // Implementation details

#endif
};

If the goal is to hide implementation details (for e.g. a closed library), you may need to go with the two-header approach. If you don't want to drag in dependencies just to use a class, the single-header approach can be a simple and robust solution.


To address Arton's question: It's been a while since I've looked at this, but I think the issue had to do with instantiating objects based on the public header, then assuming a different object size with the private header. At run time, an offset into the object wouldn't match, causing a memory smash. It seems like erenlender's answer covers this case with a public/private class pair.

Upvotes: 2

Spidey
Spidey

Reputation: 2589

I was wondering the same thing since I'm switching from C to C++ as my main programming language. I guess the best way is to use interfaces (abstract classes in C++): you publish a public interface, and your private implementation just use the interface as base class.

Upvotes: 0

zweihander
zweihander

Reputation: 6315

You have two header files MyClass.h and MyClass_p.h and one source file: MyClass.cpp.

Lets take a look at what's inside them:

MyClass_p.h:

// Header Guard Here
class MyClassPrivate
{
public:
    int a;
    bool b;
    //more data members;
}

MyClass.h:

// Header Guard Here
class MyClassPrivate;
class MyClass
{
public:
    MyClass();
    ~MyClass();
    void method1();
    int method2();
private:
    MyClassPrivate* mData;
}

MyClass.cpp:

#include "MyClass.h"
#include "MyClass_p.h"

MyClass::MyClass()
{
    mData = new MyClassPrivate();
}

MyClass::~MyClass()
{
    delete mData;
}

void MyClass::method1()
{
    //do stuff
}

int MyClass::method2()
{
    return stuff;
}

Keep your data in MyClassPrivate and distribute MyClass.h.

Upvotes: 30

sharptooth
sharptooth

Reputation: 170569

You can declare all the interfaces and constants you want to expose to the library user in a separate header file (or a set of files) and put it into "inc" subdirectory - those headers will be "public". You will also use other header files to declare classes and stuff you don't want to expose since theay are implementation details - you will put those files into "src" subdirectory - those will be "private".

This way the user will be given a hint that he has to include only the public headers - those that are in "inc" and only those headers contain the stuff he really needs, while all other headers are "private" and out of his interest area unless he wants to read into the implementation.

When you publish your library as binary - either static or dynamic library - you only copy the "inc" contents and the compilation result - those are enough for the user and this way he doesn't see your implementation sources.

Upvotes: 14

anon
anon

Reputation:

Public headers are those needed by the users of the library. Private headers are those needed to compile the library, but which are not needed by library users. Performing the split can be quite tricky, and a lot of libraries simply don't bother.

Upvotes: 2

Related Questions