Reputation: 30135
How can I "hide" parts of a class so that whoever is using the libary does not have to include headers for all the types used in my class. Ie take the MainWindow class below, ho can I have it so when compiled in a static/dynamic libary, whoever is useing the libary does NOT have to include windows.h, ie HWND, CRITICAL_SECTION, LRESULT, etc do not have to be defined.
I know I could split it into two classes, an abstract class with just the public interface, and an implementation class which is hidden that contains the members that require windows.h.
The problem here is that the visible class can no longer be created itsself, and an additional create function (eg CreateMainWindow) is required. That is fine in this case since it is most likly that just a single instance created on the heap is wanted but for other classes this is not.
class MainWindow
{
HWND hwnd;
int width, height;
std::string caption;
bool started,exited;
bool closeRequest;
unsigned loopThread;
CRITICAL_SECTION inputLock;
Input *input;
public:
static void init_type();
Py::Object getattr(const char *name);
MainWindow(int width, int height, std::string caption);
~MainWindow();
bool CloseRequest(const Py::Tuple &args);
bool CloseRequestReset(const Py::Tuple &args);
HWND GetHwnd();
int GetWidth();
int GetHeight();
Input* GetInput();
protected:
unsigned static __stdcall loopThreadWrap(void *arg);
unsigned LoopThreadMain();
LRESULT WndProc(UINT msg, WPARAM wParam, LPARAM lParam);
LRESULT static CALLBACK WndProcWrapper(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
};
Upvotes: 0
Views: 646
Reputation: 8926
As has been said before, you want to use a pimpl. I've done it and it works really well. It's totally transparent to the user of your library.
Upvotes: 0
Reputation:
One way or the other, you have two options:
Whether you expose (2) via pimpl or MyAbstractObject *o = createMyObject() is not much different.
A third option (a hack so terrible, it's funny) creates a large byte array in the object you expose to the user, and you initialize your real objects in that array using "in-place" new. Please don't do this. I'll go and wash my brains with soap.
Upvotes: 1
Reputation: 56113
You can hide parts of a class using the so-called "cheshire cat", "letter/envelope", or "pimpl" technique (which are, all, different names for the same technique):
class MainWindow
{
private:
//opaque data
class ImplementationDetails;
ImplementationDetails* m_data;
public:
... declare your public methods here ...
}
The best way is probably the abstract class mentioned in your 2nd paragraph (however I failed to understand your last sentence, in which you (tried/failed to) explain what your counter-argument to that is).
Upvotes: 7
Reputation: 140050
As you mentioned in your question, using an abstract interface is your best option. Your DLL should have factory methods for creating/destroying instances of your concrete class. I didn't quite get your point about the downside of this.
Upvotes: 4
Reputation: 74250
This book may give you some ideas:
http://www.amazon.com/Large-Scale-Software-Addison-Wesley-Professional-Computing/dp/0201633620
Large-Scale C++ Software Design
by John Lakos
Upvotes: 0