Jump to content
  • Advertisement
Sign in to follow this  
mattd

Header files in static C++ libraries

This topic is 4951 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm building a C++ library for some common classes that I use repeatedly, however I have struck a problem with the way I use header files internally and externally. If I simply allow the client application to include the library's own header files, it includes implementation-specific details, such as internal classes and types. From what I've seen, the only way to get around this is to have two sets of every class header file, one for the API with only the public members, and another for internal use with all the methods/members. Is this the only way to solve this problem? It seems like a lot of unnecessary code duplication which could lead to errors if the two versions become out of sync. I'm unable to create an pure virtual interface class for each class in one big header file and then export factory functions that return a specific implementation of this interface, as I need to be able to inherit from the class itself. I've searched the forums for posts about this, but have only found topics that are loosely related. Any suggestions would be much appreciated, as I really want to get over the interface crap and actually start making this library! - Matt D

Share this post


Link to post
Share on other sites
Advertisement
the way most libs do it is only use 1 .h file while making the library (if C++ do use namespaces to avoid name/type clashing!!)then #ifdef/#endif out stuff that shouldnt be visible
to your client app.

something to think about i guess, never really had this porblem before, what exactly do you mean by "implementation-specific details, such as internal classes and types" ?

Share this post


Link to post
Share on other sites
Quote:
Original post by mattd
I'm unable to create an pure virtual interface class for each class in one big header file and then export factory functions that return a specific implementation of this interface, as I need to be able to inherit from the class itself.


If you need to inherit from a class you'll need access to the class layout definition (regardless of where the implementation lies). It works for commercial libraries (like MFC) so I personally wouldn't worry. As for things getting out of sync - just don't edit the headers without recompiling the library!

There are a couple of obscure ways of solving the problem you have; but they're more work that it's worth.

Jans.

Share this post


Link to post
Share on other sites
Quote:
what exactly do you mean by "implementation-specific details, such as internal classes and types" ?

Well, for example, one of the classes is a generic image loader which has some libpng struct members. To get the definitions for these I need to #include <libpng.h>, something which I don't want to have to do in the client application. Same thing goes for classes using Winsock.

Share this post


Link to post
Share on other sites
If by "internal" you mean classes that the user should never need to know about, then the simple solution is to create, in each module, a header of series of headers that contain the data accessible to the user, and other headers that contain the rest of the (internal) data. This is a fairly simple solution that does not require any redundancy, and does not expose things needlessly.

On the other hand, if the user (or the user's compiler) requires information about a specific thing, it simply isn't internal, and should be made available to everyone inside a "public" header.

Share this post


Link to post
Share on other sites
The Pimpl Idiom seems to be just what you want.



// foo.h

// forward declaration of implementation class
class FooImpl;


class Foo {
friend class FooImpl;
Foo() { }
const FooImpl* impl() const;
FooImpl* impl();
public:
virtual ~Foo() { }

// Factory methods
static std::auto_ptr<Foo> create ( double value );

double value() const;
};


// foo.cpp

class FooImpl : public Foo {
friend class Foo;

// Constructors. Should be mirrored by factory methods
// in Foo
explicit FooImpl ( double value ) : value_(value) { }

double value_;
};


const FooImpl* Foo::impl() const {
return static_cast<const FooImpl*> ( this );
}
FooImpl* Foo::impl() {
return static_cast<FooImpl*> ( this );
}

std::auto_ptr<Foo> Foo::create ( double value ) {
return std::auto_ptr<Foo> ( new FooImpl ( value ) );
}

double Foo::value() const {
return impl()->value();
}

// Usage:
void bar() {
std::auto_ptr<Foo> foo = Foo::create ( 12.3 );
std::cout << foo->value() << std::endl;
}



- Neophyte

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!