C ++ DLL: don't expose whole class

How can I "hide" parts of a class so that whoever uses libary doesn't have to include headers for all types used in my class. Those. take the MainWindow class below, ho can I use it when compiled in static / dynamic library, whoever is using the library should NOT include windows.h i.e. HWND, CRITICAL_SECTION, LRESULT, etc. No need to define.

I know I can split it into two classes: an abstract class with a public interface and an implementation class that is hidden, containing the members that require windows.h.

The problem is that the visible class can no longer be instantiated by itself and an additional create function is required (like CreateMainWindow). This is fine in this case, as it is most likely that only one instance created on the heap is needed, but this is not the case for other classes.

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);
};

      

0


source to share


5 answers


You can hide parts of a class using the so-called "cheshire cat", "letter / envelope" or the "pimpl" technique (which, like everything, are 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 second paragraph (however, I was unable to understand your last sentence in which you (tried / failed) explained what your counter argument is).

+7


source


As you mentioned in your question, using an abstract interface is your best bet. Your DLL must have factory methods to create / destroy instances of your concrete class. I do not quite understand your minus.



+4


source


In any case, you have two options:

  • let the library library compiler figure out the memory size needed for your data - then the compiler can push it onto the stack
  • or allocate data on the heap for the user of the library so that the user's compiler doesn't need to know how important the data is.

Whether you expose (2) via pimpl or MyAbstractObject * o = createMyObject () is not much different.

The third option (so awful, funny) creates a large array of bytes in the object that you show to the user, and you initialize your real objects in that array with the new one in place. Please, do not do that. I'll go and wash my brain with soap.

+1


source


This book can give you a few ideas:

http://www.amazon.com/Large-Scale-Software-Addison-Wesley-Professional-Computing/dp/0201633620

Large Scale C ++ Software Development

by John Lakos

0


source


As said, you want to use pimpl. I have done this and it works really well. It is completely transparent to the user of your library.

0


source







All Articles