S
Simon Elliott
(Note: this is a real C++ question and not an MS Windows question. The
window handle I introduce is just an example of OS specific data, which
I've used to illustrate my question.)
I have some code which is dependent on MS Windows. I want to encapsulate
this in a pimpl for all sorts of reasons, the main ones being:
1/ To encapsulate the OS dependent code
2/ To allow the header not to include the OS specific header files.
(In this particular case windows.h)
This allows the header to be OS independent and further
encapsulates the OS dependent code.
Unfortunately, the code needs a window handle (HWND). What's the best
way of passing this down without having to include windows.h in the
header? (HWND is defined in windows.h.)
Effectively I want to do something like this:
=== bloggs.cpp: low level OS dependent code ===
#include "bloggs.hpp"
#include "windows.h"
class bloggs::bloggsImpl
{
private:
HWND windowHandle_; // how does this get set?
public:
bloggsImpl(void){};
};
bloggs::bloggs()impl_(new bloggsImpl){}
bloggs::bloggs(const bloggs &C)impl_(new bloggsImpl)
{
*pimpl_ = *(C.pimpl_);
}
bloggs::~bloggs()
{
delete pimpl_;
}
bloggs& bloggs:perator=(const bloggs &C)
{
*pimpl_ = *(C.pimpl_);
return(*this);
}
=== bloggs.hpp: header for low level OS dependent code ===
class bloggs
{
public:
bloggs();
bloggs(const bloggs &C);
~bloggs();
bloggs& operator=(const bloggs &C);
private:
class bloggsImpl;
bloggsImpl* pimpl_;
};
=== smith.cpp: portable code ===
#include "bloggs.hpp"
#include "smith.hpp"
class smith::smithImpl
{
private:
bloggs privateBloggs_; // must somehow give this a window handle
public:
smithImpl(void){};
};
smith::smith()impl_(new smithImpl){}
smith::smith(const smith &C)impl_(new smithImpl)
{
*pimpl_ = *(C.pimpl_);
}
smith::~smith()
{
delete pimpl_;
}
smith& smith:perator=(const smith &C)
{
*pimpl_ = *(C.pimpl_);
return(*this);
}
=== smith.hpp: header for portable code ===
class smith
{
public:
smith();
smith(const smith &C);
~smith();
smith& operator=(const smith &C);
private:
class smithImpl;
smithImpl* pimpl_;
};
=== winbits.cpp: high level OS dependent code ===
#include "smith.hpp"
#include "windows.h"
....
HWND windowHandle;
....
smith* pSmith = new smith;
pSmith->CallOneOfSmithsMethods();
delete pSmith;
I would need to add a method to tell bloggs about the window handle. But
this would have to be passed through smith, which isn't allowed to know
about such things as window handles because it must be portable and OS
independent.
In this specific example I could cheat and pass the window handle as an
unsigned long, because I happen to know the type of HWND and I happen to
know that it isn't going to change anytime soon. But a) this seems like
a bit of a kludge and b) it's a very specific solution.
It's a pity that typedefs and enums can't be forward declared like
classes can. Otherwise I could pass a pointer to HWND.
Thoughts?
window handle I introduce is just an example of OS specific data, which
I've used to illustrate my question.)
I have some code which is dependent on MS Windows. I want to encapsulate
this in a pimpl for all sorts of reasons, the main ones being:
1/ To encapsulate the OS dependent code
2/ To allow the header not to include the OS specific header files.
(In this particular case windows.h)
This allows the header to be OS independent and further
encapsulates the OS dependent code.
Unfortunately, the code needs a window handle (HWND). What's the best
way of passing this down without having to include windows.h in the
header? (HWND is defined in windows.h.)
Effectively I want to do something like this:
=== bloggs.cpp: low level OS dependent code ===
#include "bloggs.hpp"
#include "windows.h"
class bloggs::bloggsImpl
{
private:
HWND windowHandle_; // how does this get set?
public:
bloggsImpl(void){};
};
bloggs::bloggs()impl_(new bloggsImpl){}
bloggs::bloggs(const bloggs &C)impl_(new bloggsImpl)
{
*pimpl_ = *(C.pimpl_);
}
bloggs::~bloggs()
{
delete pimpl_;
}
bloggs& bloggs:perator=(const bloggs &C)
{
*pimpl_ = *(C.pimpl_);
return(*this);
}
=== bloggs.hpp: header for low level OS dependent code ===
class bloggs
{
public:
bloggs();
bloggs(const bloggs &C);
~bloggs();
bloggs& operator=(const bloggs &C);
private:
class bloggsImpl;
bloggsImpl* pimpl_;
};
=== smith.cpp: portable code ===
#include "bloggs.hpp"
#include "smith.hpp"
class smith::smithImpl
{
private:
bloggs privateBloggs_; // must somehow give this a window handle
public:
smithImpl(void){};
};
smith::smith()impl_(new smithImpl){}
smith::smith(const smith &C)impl_(new smithImpl)
{
*pimpl_ = *(C.pimpl_);
}
smith::~smith()
{
delete pimpl_;
}
smith& smith:perator=(const smith &C)
{
*pimpl_ = *(C.pimpl_);
return(*this);
}
=== smith.hpp: header for portable code ===
class smith
{
public:
smith();
smith(const smith &C);
~smith();
smith& operator=(const smith &C);
private:
class smithImpl;
smithImpl* pimpl_;
};
=== winbits.cpp: high level OS dependent code ===
#include "smith.hpp"
#include "windows.h"
....
HWND windowHandle;
....
smith* pSmith = new smith;
pSmith->CallOneOfSmithsMethods();
delete pSmith;
I would need to add a method to tell bloggs about the window handle. But
this would have to be passed through smith, which isn't allowed to know
about such things as window handles because it must be portable and OS
independent.
In this specific example I could cheat and pass the window handle as an
unsigned long, because I happen to know the type of HWND and I happen to
know that it isn't going to change anytime soon. But a) this seems like
a bit of a kludge and b) it's a very specific solution.
It's a pity that typedefs and enums can't be forward declared like
classes can. Otherwise I could pass a pointer to HWND.
Thoughts?